# Adding Affiliates (/docs/adding-affiliates)



As a store owner, affiliates can join your program in two ways:

* They can apply from your store's customer portal
* You can send them an invite from [the Affiliates dashboard](https://sell.app/dashboard/affiliates)

Anyone can apply to join your affiliate program. They do not need to have purchased from your store before, and they do not need to create their own SellApp store. This makes it easier to recruit creators, partners, and customers who can promote your digital products.

<Note>
  Invites send an application link to the affiliate's email. The affiliate still needs to complete the join flow and submit their payout details before they can promote your store.
</Note>

***

## Application Flow [#application-flow]

The standard application flow starts with a user navigating to your store's customer portal.

There, they will find an "Affiliate Program" option in the sidebar &#x2A;(provided you've enabled the affiliate program in your store's settings)*. This page will show them a general overview of your store's affiliate program, with a button that lets them apply.

You can also open [the Affiliates dashboard](https://sell.app/dashboard/affiliates), click **Invite**, and send an application link to an affiliate's email. This is handy when you already know who you want in the program.

Once the user has applied to your affiliate program, the affiliate request will be shown [in the Affiliates dashboard](https://sell.app/dashboard/affiliates)

The status of the request will depend on whether you've enabled or disabled the "Affiliate Approval" toggle in your store's affiliate settings.

* If the toggle is enabled, all affiliate requests are automatically accepted. The status of the affiliate [in the Affiliates dashboard](https://sell.app/dashboard/affiliates) will be shown as "Active"
* If the toggle is disabled, all affiliate requests need to be manually reviewed. The status of the affiliate [in the Affiliates dashboard](https://sell.app/dashboard/affiliates) will be shown as "Pending"
  * If the status is "Pending", clicking on the relevant affiliate will open a slide-over where you can accept or reject an affiliate.
  * Once rejected, an affiliate cannot submit a fresh request for the same store, but you can enable them again from the dashboard.

Once an affiliate has been accepted, they will be shown an affiliate dashboard in the customer portal. Here, they can see their earnings, copy their affiliate link, and see recent referrals and payouts.

***

## Frequently Asked Questions [#frequently-asked-questions]

### Can I disable accepted affiliates at any time? [#can-i-disable-accepted-affiliates-at-any-time]

Yes, you can always disable affiliates with an "accepted" status [in the Affiliates dashboard](https://sell.app/dashboard/affiliates). A disabled affiliate can be re-activated via the dashboard as well.

### Can I modify the "Affiliate Approval" toggle at any time? [#can-i-modify-the-affiliate-approval-toggle-at-any-time]

Yes, all your store's affiliate program settings can be modified at any time.


# Affiliate Program Software (/docs/affiliate-program-introduction)



Create an affiliate program for your SellApp store in just a few clicks, and attract affiliates who promote your digital products in exchange for a commission.

SellApp includes affiliate program software with the pieces you need to run a serious program without duct-taping spreadsheets together:

* Flexible configuration options, including the following:
  * Auto-approving new affiliates
  * Minimum payout amount
  * Percentage-based or fixed USD commissions
  * Tracking duration
  * First-referrer or last-referrer attribution
  * Supported payout methods
  * Product-level commission overrides
* A comprehensive dashboard for affiliates to keep track of their earnings, referrals, and payouts
* Notifications for new affiliate applications, pending payouts, and more
* Automatic commission calculation when orders are completed

***

## How Affiliate Tracking Works [#how-affiliate-tracking-works]

To get started with the affiliate program, it is important to know how affiliate tracking works. Start with this general overview.

1. A store can configure an affiliate program. Once enabled, users can apply to join the affiliate program from the store's customer portal
2. When users apply to join your store's affiliate program, you will receive that request [in the Affiliates dashboard](https://sell.app/dashboard/affiliates) with a status of pending
3. Once you accept the request, the affiliate can start promoting your product(s) with their unique affiliate ID
4. Whenever an affiliate refers a customer with their affiliate code, SellApp tracks the referral for the duration you configured and attributes the purchase using your selected referrer order. You can see referred purchases [in the Referrals dashboard](https://sell.app/dashboard/affiliates/referrals)
5. Once an affiliate has referred enough customers to meet the minimum payout threshold, which is defined in your store's affiliate settings, they will be eligible for a payout
6. On the **1st and 15th of the month**, you will receive a notification to pay eligible affiliates out.
7. SellApp does not handle payouts, but we do make it very easy. [The Payouts dashboard](https://sell.app/dashboard/affiliates/payouts) lets you export pending payouts with all the prerequisite information to pay your affiliates out (in bulk)

***

## Frequently Asked Questions [#frequently-asked-questions]

### How much does it cost to use the affiliate program? [#how-much-does-it-cost-to-use-the-affiliate-program]

We do not charge any additional fees for the affiliate program. It is included in SellApp's default pricing structure.

### Does this work with crypto payments? [#does-this-work-with-crypto-payments]

Yes, the affiliate program works across all current and future payment methods present on SellApp, which includes crypto payment methods.

### Does SellApp handle paying affiliates out, or do I have to do so myself? [#does-sellapp-handle-paying-affiliates-out-or-do-i-have-to-do-so-myself]

SellApp does not handle payouts, but we do make it very easy.  [The Payouts dashboard](https://sell.app/dashboard/affiliates/payouts&#x29; lets you export pending payouts with all the prerequisite information to pay your affiliates out &#x2A;*(in bulk where applicable)**

### Does the embed modal recognize affiliate referrals? [#does-the-embed-modal-recognize-affiliate-referrals]

Yes, it works out of the box and optionally supports a hardcoded `data-sell-affiliate` variable

### Can affiliates see customer information? [#can-affiliates-see-customer-information]

No, affiliates are only shown a high-level overview of their referrals. The information displayed does not include any customer information such as emails or IP addresses


# Double-sided Incentives (/docs/double-sided-incentives)



## What is a double-sided incentive? [#what-is-a-double-sided-incentive]

A double-sided incentive benefits two sides of a transaction. In the context of your store's affiliate program, this is a coupon code that is tied to a specific affiliate.

The two incentives are as follows:

1. The affiliate has the incentive to generate referrals in exchange for earning commissions
2. The referred customer has the incentive to purchase your products at a discounted price with the affiliate-specific coupon

The affiliate-specific coupon has the added benefit of being able to attribute a referral to an affiliate in a privacy-preserving and cookie-free way. This can improve affiliate tracking when customers share codes in private groups, videos, newsletters, or other places where link clicks may be harder to preserve.

***

## Creating an affiliate-specific coupon [#creating-an-affiliate-specific-coupon]

In just a few simple steps, you can create and configure an affiliate-specific coupon. Here's how:

1. Navigate to [the Affiliates dashboard](https://sell.app/dashboard/affiliates)
2. Click on the relevant affiliate to open their slide-over
3. Navigate to the "Settings" section and click on the "Affiliate Coupon" button
4. Toggle "Create Affiliate Coupon" on, then fill in the details

Finally, click the "Save" button and you're good to go. The affiliate will be able to view this coupon and share it with potential customers.

***

## Coupon Options [#coupon-options]

You can configure the coupon to your preferences. Below you will find each coupon option and its explanation.

1. **Coupon Code**: This is the coupon code a potential customer will submit when placing a purchase.
   * Should the code leak at any point in time, you can always change it to anything else of your choosing
2. **Coupon Value**: This is the value of the coupon code that will apply to the purchase, either amount-based or percentage-based
   * An amount-based discount deducts a specific amount from the purchase price.
     * If the price is $5 and the amount entered is "1", then a discount of $1 will apply and the customer will pay $4
   * A percentage-based discount deducts a percentage from the purchase price
     * If the price is $5 and the percentage entered is "10", then a discount of $0.50 will apply and the customer will pay $4.50
3. **Limit Discount**: For percentage-based coupons, you can cap the total discount amount so a big cart does not get a bigger discount than you planned
4. **Limit Usage**: When toggled off, the coupon can be used unlimited times. When toggled on, you can specify the number of times this coupon can be used for before it's disabled
5. **Expire Coupon**: When toggled off, this coupon can be used at any time. When toggled on, you can specify a date and time after which the coupon gets disabled
6. **Apply Storewide**: When toggled on, the coupon can be applied to all products in a store. You can also set a minimum spend for storewide coupons. When toggled off, a product selector will appear so you can choose exactly which products the coupon can be applied to

***

## Frequently Asked Questions [#frequently-asked-questions]

### Will the affiliate's commission be calculated based on the full price or the discounted price? [#will-the-affiliates-commission-be-calculated-based-on-the-full-price-or-the-discounted-price]

The affiliate's commission will be calculated based on the discounted price


# For Affiliates: Program Explained (/docs/for-affiliates)



<Note>
  This page is dedicated to affiliates who are either part of an affiliate program, or are looking to join an affiliate program
</Note>

If you're looking to join a store's affiliate program, or you're already an affiliate and want to know where everything lives, this page is for you.

We will start by explaining how to apply to an affiliate program, then continue with a high-level overview of each affiliate dashboard's purpose.

***

## Joining an affiliate program [#joining-an-affiliate-program]

To join an affiliate program, navigate to the store's respective customer portal. The customer portal can be found by appending /customer-portal to a store's URL

* If the store URL is bob.sell.app, then the customer portal can be found at bob.sell.app/customer-portal
* If the store URL is example.com, then the customer portal can be found at example.com/customer-portal

Once you've logged into the customer portal, you will be met with a list of your orders placed on the store. To the left of the page you will find a sidebar containing a number of options.

* If the store does not have an affiliate program present, then you will not see a dropdown called "Affiliate Program"
* If the store does have an affiliate program present, then you will see a dropdown called "Affiliate Program". Clicking any option in that dropdown will redirect you to the join page, which looks like bob.sell.app/customer-portal/affiliates/join

In the second case, where a store does have an affiliate program, you will see an overview of this affiliate program's benefits. If this is your first time applying to an affiliate program, you will see a "Become an Affiliate" button.

If the store invited you directly, the same page will show a "Complete Application" button instead.

***

For first-time affiliates who are not affiliates at other stores, clicking the "Become an Affiliate" button opens a join form where you create your affiliate profile. Note the following:

* This information cannot be changed further down the line
* The submitted information will be visible to all stores you apply to
* Your identifier becomes your affiliate code and is used to track referrals

The form also asks for your payout method, payout details, and a short message explaining why you want to join the store's affiliate program. The payout methods shown depend on what the store has enabled.

***

Once you've clicked "Save", either the store needs to review your request, or they will auto-approve your request. This depends on the store's affiliate program settings.

***

## Affiliate Dashboard Explained [#affiliate-dashboard-explained]

Once you've been accepted to the affiliate program, the customer portal should show a number of options in the "Affiliate Program". The first of which is the "Overview"

This overview is a dashboard with a high-level overview of your affiliate activity and information

1. Paid earnings, unpaid earnings, and total referral count
2. Your unique affiliate link, and optionally your unique affiliate coupon code &#x2A;(if set)*
3. Your most recent referrals generated for the store
4. Your most recent payouts

***

## Products Dashboard Explained [#products-dashboard-explained]

The second dropdown option is the "Products" dashboard

This dashboard also displays your affiliate link, as shown in the dashboard overview.

In addition, the dashboard displays a list of products with a breakdown of their price and commission rate. This can come in handy to see which products are eligible for a commission, and what the commission rates are.

A store can assign custom commission rates per product, on an affiliate-by-affiliate basis. If this is the case for you, this dashboard will display those custom rates.

***

## Referrals Dashboard Explained [#referrals-dashboard-explained]

The third dropdown option is the "Referrals" dashboard

This dashboard displays a list of all referrals generated by you, each displaying the date, status, and commission earned.

Clicking on a specific referral will open a slide-over that displays a breakdown of how the commission has been calculated, alongside a timeline of the referral's statuses.

***

## Payouts Dashboard Explained [#payouts-dashboard-explained]

The fourth dropdown option is the "Payouts" dashboard

This dashboard displays a list of all payouts associated with your affiliate profile, each displaying the date, status, and payout amount.

Clicking on a specific payout will open a slide-over that displays a breakdown of how the payout has been calculated, alongside a list of associated referrals and a timeline of the payout's statuses.

***

## Affiliate Settings Explained [#affiliate-settings-explained]

The fifth and final dropdown option is the "Settings" overview

This overview helps you modify your payout details, should you need to do so at any time. When updating your payout details, subsequent payouts will be sent to the new payout details.

Additionally, you will be shown your unique affiliate coupon code &#x2A;(if set)* and a description of this coupon's properties.

The coupon can be used to further incentivize potential customers to make a purchase, resulting in you earning more referrals.

***

## Frequently Asked Questions [#frequently-asked-questions]

### How much does it cost to apply to an affiliate program? [#how-much-does-it-cost-to-apply-to-an-affiliate-program]

No fees are charged for affiliates applying to an affiliate program. Additionally, you should also not be charged any fees for payouts or the like, except for potentially applicable payment processor fees.

### Can I join multiple affiliate programs? [#can-i-join-multiple-affiliate-programs]

Yes, you can join as many affiliate programs as you like.

### How do I refer customers? [#how-do-i-refer-customers]

Copy your unique affiliate link and send it over to the potential customer. Ensure that you do not remove the `?affiliate=[affiliateIdentifier]` value from the URL, as this is what is used to attribute a purchase to you.

You can also copy unique product URLs in the Products dashboard.

### Can I get paid out in... [#can-i-get-paid-out-in]

This depends entirely on the store's payout settings. Where certain stores can only pay out in some payment methods, other stores can pay out in other payment methods.

### How long does it take before I get paid out for referrals generated? [#how-long-does-it-take-before-i-get-paid-out-for-referrals-generated]

This depends on a number of factors. The first factor is what payment method the customer has paid with.

* **For fiat payment methods**, such as PayPal or Stripe, the eligible for payout date is **30 days** after a purchase has been made.
  * This measure is in place to prevent affiliate fraud and factor in potential charge-backs.
* **For crypto payment methods**, such as Bitcoin, the eligible for payout date is **immediately** once the purchase has been made.
  * This is because crypto payments are irreversible and are thus not prone to fraud

On the first and fifteenth of every month, eligible referrals are calculated and a payout is generated.

The store is then notified that the payouts are ready to be paid, after which the store manually sends the funds to your payout details.

<Warn>
  If your commission amount is less than the "Minimum Payout" amount specified by the store, then your payout will not be generated until you have exceeded the threshold.
</Warn>


# Set Up an Affiliate Program (/docs/getting-started-affiliate-program)





There are only two steps involved in launching an affiliate program for your SellApp store. After setup, affiliates can apply, share referral links, and earn commissions when tracked orders are completed.

The first step is to navigate to [your store's affiliates settings](https://sell.app/dashboard/settings?settings=affiliates). This will display a list of configurable options for your store.

<img src="`${docsBasePath}/images/affiliate-settings.webp`" alt="SellApp store affiliate settings" className="rounded-xl w-full shadow-lg" />

The second step is to fill each of these options in with the values of your choosing, and then save the changes. Once you've done that, you're good to go.

***

## Affiliate Program Settings [#affiliate-program-settings]

The below is an overview of each of the affiliate settings and their respective purpose.

1. **Affiliate Program toggle**: Enable or disable your store's affiliate program
2. **Affiliate Approval toggle**: Automatically or manually approve new affiliate requests
3. **Referral Commission Input**: Specify how much commission an affiliate can earn for each referral.
   * You can set either an amount-based value in USD, or a percentage-based value.
4. **Minimum Payout Balance input**: Specify how much an affiliate needs to earn in commissions before being eligible for a payout
5. **Tracking Duration input**: Specify for how long the affiliate can earn a commission on a customer's purchase.
   * For example, if this is set to 1 day, the affiliate only has 1 day for the visitor to make a purchase in order for them to be eligible for a commission.
     * If they referred a customer 2 days ago, then the affiliate would not be eligible for a commission any longer
     * If this is set to 10 days, the affiliate has 10 days for the visitor to make a purchase in order for them to be eligible for a commission
6. **Referrer Order dropdown**: Specify which referrer should be credited with a sale, in the case where a customer clicks on two referral links
   * The first referrer option credits is the affiliate who was first in referring the customer to your product
   * The last referrer option credits is the affiliate who most recently referred the customer to your product
7. **Payout Methods checkbox**: Select the payment methods you are able to pay affiliates out with
8. **Custom Products toggle**: Override the default referral commission from point 3, then choose exactly which products affiliates can promote and what commission each product pays

***

## Frequently Asked Questions [#frequently-asked-questions]

### Can I specify a custom commission rate on an affiliate-by-affiliate basis? [#can-i-specify-a-custom-commission-rate-on-an-affiliate-by-affiliate-basis]

Yes, once you approve an affiliate you can do so in the respective affiliate's slide-over.

### Do I have to configure any code on the storefront? [#do-i-have-to-configure-any-code-on-the-storefront]

No, everything is configured and ready to go out of the box. No code changes are required, unless you want to hard-code the `data-sell-affiliate` variable in your embed modal.


# Handling Payouts (/docs/handling-payouts)



Affiliate payouts can be viewed at any time [in the Payouts dashboard](https://sell.app/dashboard/affiliates/payouts). SellApp calculates eligible commissions and gives you the export data needed to pay affiliates through your chosen payout methods.

***

## Payouts Dashboard [#payouts-dashboard]

[The Payouts dashboard](https://sell.app/dashboard/affiliates/payouts) displays all affiliate payouts. Since all payouts are displayed regardless of their status or payout method, we have added two filters that help narrow things down.

The first filter helps display payouts with a specific status. The status of each payout is either "Due" or "Paid".

The second filter helps display payouts that are to be paid in a specific payment method. This filter can be used in conjunction with the export functionality in order to generate valid CSV exports for bulk payouts.

For example, if you need to filter the payouts table for payouts that are due, and affiliates expecting to receive their payout sent to their PayPal account, you would do the following:

1. Set the &#x2A;*"Status"*&#x2A; dropdown to &#x2A;*"Due"**
2. Set the &#x2A;*"Payout method"*&#x2A; to &#x2A;*"PayPal"**

The resulting table will exclusively display payouts that are due and to be paid out with PayPal. Subsequently, you can export these payouts by clicking the checkbox at the top left -> "Select All" -> "Export"

SellApp will start the export in the background and notify you when the payout data is ready to download. The CSV is formatted in such a way that you can import it to your PayPal account and pay all of these affiliates at one time.

Once you have paid the affiliates via the respective payment method, &#x2A;*please make sure to navigate back to the Payouts dashboard and mark the respective payouts as "paid"**.

***

## Payout Slide-over [#payout-slide-over]

The payout slide-over provides a breakdown of the payout created. The first section displays a breakdown of how the affiliate's payout is calculated.

The second section displays a table of referrals associated with this payout. Each individual referral can be viewed as well via the respective quick-action button.

The third and final section displays a timeline of the payout, including when it was created, and paid.

The slide-over also displays a number of quick actions: updating a payout's status, and displaying the associated affiliate.

***

## Frequently Asked Questions [#frequently-asked-questions]

### How do I use PayPal Mass Pay? [#how-do-i-use-paypal-mass-pay]

To pay your affiliates with PayPal Mass Pay, you need to own a verified PayPal business account. If this is the case, proceed with applying for PayPal Mass Pay:

1. Sign in to your PayPal account and click the "Pay & Get Paid" button at the top of the page
2. Click ["Payouts"](https://www.paypal.com/payoutsweb/batchFileUpload?entry=nav) that is shown under "Make Payments"
3. Fill in the form by answering the four questions asked
4. Finally, click the "Submit" button

Once done, you will need to wait for up to 3 days for PayPal to review and accept your request

### When are payouts generated? [#when-are-payouts-generated]

Payouts are generated on the first and fifteenth of every month.

### When are referrals eligible for a payout? [#when-are-referrals-eligible-for-a-payout]

Referrals become eligible for a payout once their status is "Accepted" and their eligible for payout date has been met. The eligible for payout date depends on the payment method the customer has paid with:

* **For fiat payment methods**, such as PayPal or Stripe, the eligible for payout date is **30 days** after the purchase has been made.
  * This measure is in place to prevent affiliate fraud and factor in potential charge-backs.
* **For crypto payment methods**, such as Bitcoin, the eligible for payout date is **immediately** once the purchase has been made.
  * This is because crypto payments are irreversible and are thus not prone to fraud


# Managing Affiliates (/docs/managing-affiliates)



Affiliates can be managed at any time [in the Affiliates dashboard](https://sell.app/dashboard/affiliates). Use this dashboard as the control center for affiliate management, custom rates, affiliate coupons, referral activity, and payout history.

***

## Affiliates Dashboard [#affiliates-dashboard]

[The Affiliates dashboard](https://sell.app/dashboard/affiliates) provides a general overview of all affiliates present in your store's affiliate program.

The dashboard also helps you perform the following quick actions:

1. Inviting affiliates by email
2. Accepting or rejecting pending affiliate requests
3. Disabling and/or re-enabling affiliates
4. Opening a specific affiliate's slide-over

***

## Affiliate Slide-over [#affiliate-slide-over]

The affiliate slide-over provides a more in-depth overview of an affiliate, which is split up into a number of tabs.

1. The first tab displays an overview of the affiliate's information. Of note is the "Settings" section, which consists of two buttons:
   * Affiliate Coupon: Create an affiliate-specific coupon which the affiliate can use for the following
     * To further incentivize potential customers to purchase your product(s)
     * It's another, privacy-preserving, way of associating an affiliate with a purchase
   * Custom Rates: Affiliate-specific rates and eligible products which this affiliate can promote
2. The second tab displays a table of recent referrals generated by this affiliate
3. The third tab displays a table of recent payouts associated with this affiliate
4. The fourth and fifth tab display the affiliate's total earnings, and the amount of earnings which have not been paid yet.

***

## Frequently Asked Questions [#frequently-asked-questions]

### Can I disable accepted affiliates at any time? [#can-i-disable-accepted-affiliates-at-any-time]

Yes, you can always disable affiliates with an "Active" status [in the Affiliates dashboard](https://sell.app/dashboard/affiliates). A disabled affiliate can be re-activated via the dashboard as well.

### Can I modify the "Affiliate Approval" toggle at any time? [#can-i-modify-the-affiliate-approval-toggle-at-any-time]

Yes, all your store's affiliate program settings can be modified at any time.


# Managing Referrals (/docs/managing-referrals)



Affiliate referrals can be managed at any time [in the Referrals dashboard](https://sell.app/dashboard/affiliates/referrals). This is where referral tracking, commission review, and referral status decisions live.

***

## Referrals Dashboard [#referrals-dashboard]

[The Referrals dashboard](https://sell.app/dashboard/affiliates/referrals) provides a general overview of all referrals generated by affiliates.

The dashboard also helps you perform the following quick actions:

1. Accept, review, or reject a referral when the current status allows it
2. Opening a specific referral's slide-over

***

## Referral Slide-over [#referral-slide-over]

The referral slide-over provides a breakdown of the referral created. The first part displays how the affiliate's commission is calculated.

The second part displays a timeline of the referral, including when it was created, reviewed, and accepted.

The slide-over also displays a number of quick actions: updating a referral's status, displaying the associated invoice or affiliate, and opening the associated payout when one exists.

***

## Frequently Asked Questions [#frequently-asked-questions]

### Can I update a previously rejected referral to an accepted status? [#can-i-update-a-previously-rejected-referral-to-an-accepted-status]

No, once you reject a referral, it is no longer possible to update its status to accepted at a later stage. As such, we only advise rejecting a referral if and when you are certain that you don't want to update the status at a later date.

Should you wish to keep the optionality, we advise changing the status to "In Review" instead.


# Sell Community Access (/docs/community-introduction)



Community lets you sell paid access to the places your customers already use: Discord servers, Telegram groups or channels, Slack channels, and WhatsApp groups. It works for memberships, subscriptions, private communities, paid support rooms, and buyer-only access spaces.

The flow is always the same:

1. Connect the platform from [Community settings](https://sell.app/dashboard/settings?settings=community).
2. Add the server, group, or channel you want SellApp to manage.
3. Open a product, expand **Community**, and choose which access should be granted after purchase.
4. Decide whether linking is required at checkout and whether access should be removed when a subscription expires.

SellApp tracks the grant on the order, shows pending actions when a platform needs the customer to join, and gives you a Health view for setup issues like missing bot access or Discord role hierarchy problems.

***

## Platform differences [#platform-differences]

Discord can grant one or more roles inside a connected server, which makes it a strong fit for a paid Discord server or role-based membership. The customer connects their Discord account during checkout when the product requires it.

Telegram adds customers to a connected group or channel. Setup uses a verification code flow, so you do not need to create your own Telegram app.

Slack grants access to channels in a connected workspace. Customers are invited through your workspace invite link, then SellApp handles the channel access.

WhatsApp grants access to groups. The customer confirms their phone number, then joins the group so SellApp can approve the request.

***

## Before you attach access to products [#before-you-attach-access-to-products]

Make sure the platform is connected and healthy first. If SellApp cannot see a Discord role, cannot access a Slack channel, or cannot verify a WhatsApp group, that issue will carry into checkout.

For subscription products, keep the expiry setting switched on when access should only last for the paid period. SellApp will revoke community access when the subscription expires or is cancelled, so access stays tied to the customer's paid status.


# Paid Discord Server Roles (/docs/discord-roling)





Use Discord roles when a product should unlock a paid Discord server, private buyer role, VIP room, or any other server access after checkout. SellApp can use the official SellApp bot, or your own custom bot if you want the Discord invite and role grant to come from your brand.

***

## Video Guide [#video-guide]

We've created a step-by-step video guide that will help you set up and configure your Discord bot correctly. If you prefer a text-based guide, please proceed to scroll down.

<video className="rounded-xl w-full">
  <source src="`${docsBasePath}/images/discord.mp4`" type="video/mp4" />

  Your browser does not support the video tag.
</video>

***

## Connect Discord [#connect-discord]

Start in [your SellApp community settings](https://sell.app/dashboard/settings?settings=community), then open **Discord**.

1. Click **Add** under **Connected Accounts** and connect your Discord account.
2. Click **Add** under **Connected Servers** and choose the server you want customers to join.
3. Invite the bot if SellApp shows the server as pending.
4. Click **Sync Roles** after adding or changing roles in Discord.

<Note>
  Make sure the bot's role is above the role(s) you are trying to grant. If it is too low in your Discord server's role list, the bot will not be able to assign those roles after a successful purchase.
</Note>

SellApp checks Discord health automatically. If it detects a role hierarchy issue, the Discord settings page shows which products may be affected and lets you re-check after you fix the role order.

***

## Using a custom bot [#using-a-custom-bot]

The official bot is enough for most stores. If you want to use your own bot, click **Custom Bot** in the Discord settings panel and create a Discord bot [in the Discord Developer Portal](https://discord.com/developers/applications).

1. Click "New Application" at the top right hand side.
2. Once your bot is created, retrieve your client ID and secret from the OAuth2 page, then add the following redirect URLs:
   * [https://sell.app/discord/connect-account](https://sell.app/discord/connect-account)
   * [https://sell.app/discord/connect-customer](https://sell.app/discord/connect-customer)
   * [https://sell.app/discord/connect-guild](https://sell.app/discord/connect-guild)
3. Retrieve your bot token from the Bot page.
4. Paste the client ID, client secret, and bot token into SellApp, then save.
5. When adding your first server, choose **Custom Bot**. Existing stores can switch all connected servers between official and custom mode from the Discord server menu.

***

## Add Paid Discord Access to a Product [#add-paid-discord-access-to-a-product]

Once your account and server are connected, open a product and expand **Community**. Select the Discord server, add one or more roles, then choose whether Discord authorization is required at checkout.

You can also decide whether SellApp should kick the customer from the server when a subscription expires. Keep this enabled when Discord access is part of the paid subscription, membership, or recurring community product.

You will also be able to update your products in bulk. Select products in [your products dashboard](https://sell.app/dashboard/listings), open **Bulk update**, then choose **Discord invite**.

Happy selling!


# Paid Slack Channel Access (/docs/slack-access)



Use Slack access when your product should unlock a paid private channel inside a Slack workspace. SellApp connects to your workspace, reads the channels the app can access, and grants customers access after checkout.

***

## Connect Slack [#connect-slack]

Start in [your SellApp community settings](https://sell.app/dashboard/settings?settings=community), then open **Slack**.

1. Click **Connect workspace** and approve the SellApp Slack app.
2. Add your workspace invite link. Customers use this link to join the workspace before channel access can be completed.
3. Make sure the SellApp app is a member of each channel you want to sell.
4. Click **Add channel**, choose the channel, then save it.

Use **Check Health** on a channel after changing Slack permissions. If SellApp says the bot is not a member, invite the app to that channel and check again.

<Note>
  Slack needs a valid workspace invite link before you can add paid channels. Without it, customers may be eligible for the channel but unable to join the workspace.

  Slack authorization links contain protected state bound to your user and store and expire after 15 minutes. Use the link from your latest **Connect workspace** attempt. Connections started before protected OAuth state was introduced cannot be resumed; if an older authorization returns an error, click **Connect workspace** again. SellApp intentionally rejects legacy unsigned state values.
</Note>

***

## Add Slack to a product [#add-slack-to-a-product]

Open a product, expand **Community**, then choose the Slack channel.

Slack channel access is handled as a post-purchase grant. Keep **Remove from channel on subscription expiry** enabled when the channel should only stay available while the subscription or membership is active.

***

## What customers see [#what-customers-see]

Customers use your Slack workspace invite to join the workspace. After the order is completed, SellApp grants the configured channel access and shows pending access on the order if the customer still needs to complete the join step.

If a grant looks stuck, open the order and check the **Community Access** panel. It will show whether Slack is processing, waiting on the customer, or needs manual attention.


# Paid Telegram Group Access (/docs/telegram-access)



Use Telegram access when a product should unlock a paid Telegram group, supergroup, or channel. SellApp uses the official Telegram bot and a verification code flow, so there is no custom bot setup to maintain.

***

## Connect Telegram [#connect-telegram]

Start in [your SellApp community settings](https://sell.app/dashboard/settings?settings=community), then open **Telegram**.

1. Click **Connect group/channel**.
2. SellApp will generate a verification code.
3. Add the SellApp Telegram bot to the group or channel you want to sell access to.
4. Post the verification code in that group or channel.
5. Return to SellApp and wait for the group or channel to appear.

After it is connected, use **Check Health** if you want to confirm the bot can still manage that group or channel. SellApp also checks stale connections automatically.

<Note>
  The bot needs enough permission to manage membership. If a health check fails, make the bot an admin in Telegram, then run the check again.
</Note>

***

## Add Telegram to a product [#add-telegram-to-a-product]

Open a product, expand **Community**, and choose the Telegram group or channel. Then decide whether the customer must link Telegram during checkout.

If linking is required, checkout will stop until the customer connects Telegram. If it is optional, SellApp can still show the access step without blocking the order.

For subscription products, keep **Kick from group on subscription expiry** enabled when the customer should lose paid community access after cancellation or failed renewal.

***

## What customers see [#what-customers-see]

During checkout, customers are asked to connect Telegram when the product requires it. Once the order completes, SellApp creates the community grant and tracks the result on the order.

If something needs attention later, check the order's **Community Access** panel and the Community Health page.


# Paid WhatsApp Group Access (/docs/whatsapp-access)



Use WhatsApp access when a product should unlock a paid private WhatsApp group. Customers confirm their phone number during checkout, then SellApp approves the join request once the order is paid.

***

## Connect WhatsApp [#connect-whatsapp]

Start in [your SellApp community settings](https://sell.app/dashboard/settings?settings=community), then open **WhatsApp**.

1. Click **Add group**.
2. Scan the QR code shown by SellApp.
3. Wait for SellApp to load the groups available in that WhatsApp session.
4. Select the group you want to sell access to.
5. Add the SellApp bot phone numbers as group admins.
6. Enable **Approve new members** in the WhatsApp group.

After the group is added, SellApp checks whether the bot is an admin and whether approval mode is enabled. Fix any warnings before attaching the group to a product.

<Note>
  WhatsApp access depends on approval requests. If **Approve new members** is off, SellApp cannot safely approve paid customers into the group.
</Note>

***

## Add WhatsApp to a product [#add-whatsapp-to-a-product]

Open a product, expand **Community**, and choose the WhatsApp group. Then decide whether the customer must confirm WhatsApp during checkout.

For subscription products, keep **Kick from group on subscription expiry** enabled when paid group access should end with the subscription.

***

## What customers see [#what-customers-see]

During checkout, customers enter their WhatsApp phone number when the product requires it. After purchase, they join the group with that same phone number.

SellApp tracks the grant while the customer is waiting to join, then marks it granted after the join request is approved. If the customer uses a different phone number, the order can stay in a pending state until it is fixed.

Use the order's **Community Access** panel to see whether WhatsApp is processing, awaiting the customer, granted, or needs manual action.


# Trustpilot Review Invitations (/docs/trustpilot)



With SellApp, you can automatically invite customers to leave a review on your Trustpilot page after they purchase from your digital product store.

***

## Trustpilot Review Invitation Setup [#trustpilot-review-invitation-setup]

To start, head to [your Trustpilot invitation settings by clicking here](https://businessapp.b2b.trustpilot.com/invitations/eti-settings).

1. On this page you'll find a unique Trustpilot email address. Click the "Copy email address"
2. With the copied email address, head on over to [your SellApp storefront personalization settings by clicking here](https://sell.app/dashboard/settings?settings=personalization) and paste the unique email you copied in step 1 into the "Trustpilot Email" input, then click the "Save" button

That's it. Now, when SellApp sends the customer their delivery email after a purchase, Trustpilot can use that email to invite them to place a review on your Trustpilot page.

### How it works [#how-it-works]

Whenever the delivery email is sent, your Trustpilot email is BCC'ed into the email that is sent to your customer. This BCC'ed Trustpilot email is then used by Trustpilot to automatically send an invitation to the customer's email to leave a review.

The limitation lies in the number of invites you can send out. For non-paying Trustpilot members, you will only be able to send out 100 invitations per month after which the invites stop being sent out. For most stores this is plenty enough, but for others it might make sense to purchase a plan.

For more info, head on over to Trustpilot's [automatic feedback service (AFS) page by clicking here](https://businessapp.b2b.trustpilot.com/invitations/eti-settings).


# Store Notifications (/docs/creating-notifications)





You may want to receive a notification when a specific event happens on your SellApp store, such as when an order gets completed, a support ticket is created, or another store event needs attention.

<img src="`${docsBasePath}/images/notifications.webp`" alt="Sample Discord notification" className="rounded-xl w-full max-w-xl shadow-lg" />

<Note>
  Currently, you can create Discord notifications and email notifications. More notification channels will be added in the future.
</Note>

***

## Setting up Discord channel notifications [#setting-up-discord-channel-notifications]

1. **Get yourself a webhook URL from your Discord server**
   1. Right click the Discord channel where you'd like to receive notifications and click "Edit Channel"
   2. Navigate to "Integrations" and click "Create Webhook"
   3. Click "Copy Webhook URL" and save this somewhere, you're going to paste this in step 2.2

2. **Add Discord webhook URL to SellApp**
   1. Navigate [to your SellApp storefront notifications](https://sell.app/dashboard/settings?settings=notifications) and click "Add Channel"
   2. Select "Discord" as the channel type, add a reference you can remember for the channel name, and paste the webhook URL you got from step 1.1. in the "Webhook Url" input field.
   3. Select the notifications you'd like to receive on your channel. For example, if you only want to receive completed order notifications, select "Order Completed" here. Finally, click "Save" to complete the setup.

There you go. Now, specified notifications are sent near-instantly to the Discord channel you entered.

You can also click **Send Test Notification** while configuring a Discord channel to make sure the webhook is working before you rely on it.

***

## Setting up email notifications [#setting-up-email-notifications]

1. Navigate [to your SellApp storefront notifications](https://sell.app/dashboard/settings?settings=notifications) and click "Add Channel"
2. Select "Email" as the channel type and enter the email address in the "Email" input field.
3. Select the notifications you'd like to receive to your email. For example, if you only want to receive completed order notifications, select "Order Completed" here. Finally, click "Save" to complete the setup.

There you go. Now, specified notifications are sent near-instantly to the email address you entered.


# Sell Subscriptions Online (/docs/creating-subscriptions)





With SellApp, you can sell subscriptions online by creating products with recurring prices. Customers are charged at a predefined period of time, for example: **daily**, **weekly**, **monthly**, or **yearly**.

This pricing type is ideal for digital products that require continuous maintenance and effort, with good examples being SaaS software, paid communities, memberships, and resources that are updated regularly.

Let's dive into how you can create a product with a recurring subscription.

<Note>
  Currently, subscription products require a payment method that supports subscriptions, such as [Stripe](/stripe) or [PayPal](/paypal).
</Note>

***

## Create a Subscription Product [#create-a-subscription-product]

* Start by creating or editing a product [in the product dashboard](https://sell.app/dashboard/listings).
* In the "Pricing" section, select "Subscription" as the pricing type.
  * Once you've enabled the subscription pricing type, you can proceed to set your price and duration for the subscription.
  * Here's a preview of what that looks like:
  <img src="`${docsBasePath}/images/subscriptions.webp`" alt="Creating a subscription" className="rounded-xl w-full shadow-lg" />
  * Specify any kind of subscription duration you'd like. Charge customers every X days, weeks, months, or years. The highest duration supported is currently 365 days, 52 weeks, 12 months, or 1 year, so you cannot set the duration to be more than a year.
* Once saved, customers can purchase this newly created subscription product.
  * We'll handle setting up the subscription and notifying the customer if a payment happens to fail.
  * You'll be able to see how many subscriptions are active and how many payments have been made in your [SellApp subscription dashboard](https://sell.app/dashboard/subscriptions)

***

## Control renewal delivery [#control-renewal-delivery]

Each subscription variant has a **Redeliver on renewal** setting under **Subscription lifecycle**. It is enabled by default.

Keep it enabled when customers should receive the plan's deliverables again after every successful renewal. Disable it when the renewal should extend access without reissuing downloadable files, serials, bundle items, or other one-time fulfillment.

This setting does not stop billing or cancel the subscription. Renewals still create their normal order record and send renewal notifications and webhooks. The policy follows the customer's current plan variant, including after a supported plan change.

***

## Manage subscriptions [#manage-subscriptions]

Open [Subscriptions](https://sell.app/dashboard/subscriptions) to review active subscriptions and open a subscription detail page. Depending on the payment provider and subscription state, you can cancel, pause, resume, change the renewal date, or review pending lifecycle actions.

Customers can manage supported actions from the customer portal. Some actions are intentionally customer-only because the customer owns the payment instrument or must approve a provider redirect.

For API integrations, use the [Subscriptions API](/api/subscriptions) to check capabilities before showing lifecycle actions. The API supports idempotency for retries through the `Idempotency-Key` header or `idempotency_key` request field.


# Payment Method Discounts (/docs/discounting-payment-methods)



Offering a discount or adding a fee to a specific payment method is as easy as modifying the payment method in question. Use this when you want to encourage a lower-cost checkout option or pass through a fee for a specific processor.

**Here's how to do so:**

1. Go to your [store's payment settings](https://sell.app/dashboard/settings?settings=payment)
2. For the payment method in question, click its name so its respective modal appears.
3. In the **Discount/Fee** section, enter a percentage, a fixed amount, or both.
   * To add a discount, enter positive values. For example, for a 10% discount, enter `10` in the percentage field.
   * To add a fee, enter negative values. For example, for a 5% fee, enter `-5` in the percentage field.
   * If you use both percentage and fixed amount, they must both be discounts or both be fees.
4. Save the payment method.

That's all done. The payment method in question will now have a fee or discount applied, which will be visible to the end-user during the checkout process.


# Embed Digital Products (/docs/embedding-products)





SellApp's embed modal lets customers buy products from your own website without being redirected to a SellApp product page. It works on any website or codebase and will not affect your site's design.

<img src="`${docsBasePath}/images/embed.webp`" alt="Toggle Embed" className="rounded-xl w-full max-w-xl shadow-lg" />

Use it when you want to sell from your own landing page, blog, community site, or custom storefront while still letting SellApp handle checkout.

***

## Add the embed [#add-the-embed]

The easiest way to get the embed code is from your products dashboard:

1. Open [your products dashboard](https://sell.app/dashboard/listings).
2. Select the product or products you want to embed.
3. Choose **Embed Code** from the action bar.
4. Paste the generated button where customers should click.
5. Add the embed script once on the page.

```html
<script src="https://cdn.sell.app/embed/script.js" type="module"></script>
```

You only need to load the script once per page, even when the page has multiple product buttons.

<Note>
  If your generated snippet includes an extra stylesheet line, keep it with the snippet. The dashboard always gives you the safest version for your store.
</Note>

***

## Product buttons [#product-buttons]

A product button needs your store ID and product ID. When a customer clicks it, the checkout opens on your website.

```html
<button
  data-sell-store="123"
  data-sell-product="456"
>
  Buy now
</button>
```

Use one button per product or offer. You can also add optional details, such as a starting quantity, coupon, theme color, or customer email.

***

## Cart buttons [#cart-buttons]

You can also add a cart button for customers who want to review what they have added before paying.

```html
<button
  data-sell-cart
  data-sell-store="123"
>
  View cart
</button>
```

The cart stays available for returning visitors for a short period, so customers can come back and continue checkout.

If you want a product button to use single-product checkout only, add `data-sell-disable-cart="true"`. This hides cart actions in the modal and ignores any saved cart for that button.

```html
<button
  data-sell-store="123"
  data-sell-product="456"
  data-sell-disable-cart="true"
>
  Buy now
</button>
```

If your developer wants to open the cart from another part of your site, they can use:

```js
window.openCheckoutCart('123', {
  darkMode: true,
  theme: '#f97316',
  language: 'en',
})
```

***

## Button options [#button-options]

You can customize a button by adding extra `data-sell-*` attributes. These are optional unless marked as required.

| Attribute                  | Description                                                                                                               |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `data-sell-store`          | Required store ID.                                                                                                        |
| `data-sell-product`        | Required product ID for product buttons.                                                                                  |
| `data-sell-variant`        | Opens a specific variant immediately.                                                                                     |
| `data-sell-quantity`       | Sets the starting quantity. Use a number, such as `3`.                                                                    |
| `data-sell-coupon`         | Applies a coupon code when the modal opens.                                                                               |
| `data-sell-email`          | Prefills the customer's email address.                                                                                    |
| `data-sell-extra`          | Sets a starting extra amount for pay-what-you-want products.                                                              |
| `data-sell-payment_method` | Starts checkout with a preferred payment method selected.                                                                 |
| `data-sell-affiliate`      | Attributes the order to an affiliate identifier. If omitted, `affiliate` or `aff` from the page URL is used when present. |
| `data-sell-disable-cart`   | Use `true` to disable cart functionality for this product button.                                                         |
| `data-sell-hide-stock`     | Use `true` to hide stock and availability counts in the modal.                                                            |
| `data-sell-darkmode`       | Use `true` to open the modal in dark mode.                                                                                |
| `data-sell-theme`          | Sets the checkout accent color, such as `#f97316`.                                                                        |
| `data-sell-language`       | Opens checkout in a chosen language.                                                                                      |
| `data-sell-locale`         | Alias for `data-sell-language`.                                                                                           |

For language, you can use values like `en`, `de`, `fr`, `nl`, `es`, or `pt-BR`.

For payment methods, use the gateway value for the payment option you want to preselect, such as `STRIPE`, `PAYPAL`, `CASHAPP`, `MERCADO_PAGO`, `MOLLIE`, `RAZORPAY`, `SQUARE`, `PADDLE`, `PAYSTACK`, `VENMO`, `AUTHNET`, or `NMI`. Crypto values include `BTC`, `ETH`, `SOL`, `LTC`, `XMR`, and the other crypto options enabled on your store. For custom payment methods, use the full custom method value shown by SellApp.

***

## Promotions in the embed [#promotions-in-the-embed]

The embed modal shows the same active promotion state as your storefront checkout. If a promotion applies, customers can see the discount; if they are below a promotion minimum, the modal can show how much more they need to add; and if a coupon blocks a non-stackable promotion, the embed will keep the promotion from applying.

***

## Checkout info prefills [#checkout-info-prefills]

If your product asks customers for extra checkout information, you can prefill those fields too. Use the field key from the checkout information field in SellApp.

The key is not the field label customers see at checkout. For example, a field labeled "In-game username" may have a key like `4124bc0a9335c27f086f24ba207a4912`. Copy the key from SellApp and place it after `data-sell-checkout-`.

```html
<button
  data-sell-store="123"
  data-sell-product="456"
  data-sell-checkout-4124bc0a9335c27f086f24ba207a4912="JohnDoe123"
>
  Buy now
</button>
```

This is useful when the customer is already logged in on your site and you already know details such as their username, license name, or another field your product asks for.

***

## Full button example [#full-button-example]

This example opens a specific variant, applies an orange accent color, adds a coupon, sets quantity, prefills email, and fills a checkout field.

```html
<button
  data-sell-store="123"
  data-sell-product="456"
  data-sell-variant="789"
  data-sell-darkmode="true"
  data-sell-theme="#f97316"
  data-sell-language="pt-BR"
  data-sell-coupon="LOYAL10"
  data-sell-quantity="10"
  data-sell-hide-stock="true"
  data-sell-payment_method="MERCADO_PAGO"
  data-sell-email="johndoe@example.com"
  data-sell-checkout-4124bc0a9335c27f086f24ba207a4912="JohnDoe123"
>
  Buy credits
</button>
```

***

## Modern websites [#modern-websites]

The embed is designed to work on static websites, landing page builders, and modern app-style websites. If your site loads product buttons after the page first opens, the embed usually detects them automatically.

If your developer needs to manually refresh the embed buttons, they can call:

```js
window.refreshCheckoutEmbed()
```


# Link a Custom Domain (/docs/linking-custom-domain)





By default, your SellApp storefront comes with a free subdomain, for example: **admin.sell.app**. You can also add a custom domain of your own, for example: **admin.com**, so your digital product store lives on your own brand.

**It is completely free to add a custom domain to your SellApp storefront.**

***

## **Video Guide: Root Domain** [#video-guide-root-domain]

In the following video guide we visually show you how to configure a **root** domain such as **example.com**, **bob.com**, or **varrock.osrs**.

For you to follow this guide step-by-step, you will want to change your domain's DNS provider to Cloudflare. It's free and easy to do so.

<video className="rounded-xl w-full">
  <source src="`${docsBasePath}/images/custom-domain.mp4`" type="video/mp4" />

  Your browser does not support the video tag.
</video>

If you prefer a text-based guide, please proceed to scroll down to "Step 1".

***

## **Video Guide: Subdomain** [#video-guide-subdomain]

In the following video guide we visually show you how to configure a **subdomain*&#x2A; such as &#x2A;*[www.example.com](http://www.example.com)**, **me.bob.com**, or **teleport.varrock.osrs**.

For you to follow this guide step-by-step, you will want to change your domain's DNS provider to Cloudflare. It's free and easy to do so.

<video className="rounded-xl w-full">
  <source src="`${docsBasePath}/images/custom-subdomain.mp4`" type="video/mp4" />

  Your browser does not support the video tag.
</video>

If you prefer a text-based guide, please proceed to scroll down to "Step 1".

***

## **Step 1: Buy a custom domain** [#step-1-buy-a-custom-domain]

*If you've already purchased or own a domain name, skip ahead to Step 2.*

If you don't already have a custom domain, you're going to want to buy one. We strongly suggest going with [Cloudflare](https://www.cloudflare.com) as they're easy, affordable, and have a best-in-class DNS system that comes with DDoS protection out of the box.

***

## **Step 2: Add your custom domain to SellApp** [#step-2-add-your-custom-domain-to-sellapp]

To set up your custom domain, &#x2A;*[navigate to your storefront's personalization settings](https://sell.app/dashboard/settings?settings=personalization)** -> **Custom Domain** and enter the custom domain you'd like your SellApp storefront to live on.

You can specify any domain you'd like:

1. A root domain such as **example.com**, **bob.com**, or **varrock.osrs**
2. A subdomain such as &#x2A;*[www.example.com](http://www.example.com)**, **me.bob.com**, or **teleport.varrock.osrs**

***

## **Step 3: Add the CNAME and TXT records to your custom domain's DNS settings** [#step-3-add-the-cname-and-txt-records-to-your-custom-domains-dns-settings]

In your domain's DNS settings, create the records shown in the SellApp setup wizard. For most domains, you'll see two **CNAME records** pointing your (sub)domain to **sell-beacon.net**:

1. **CNAME Record 1**
   * **Host/Name:**  \*
   * **Value**/&#x2A;*Points To:** sell-beacon.net

2. **CNAME Record 2**
   * **Host/Name:**
     * **@*&#x2A; — If you'd like to link to your root domain &#x2A;(as mentioned in point 1 above)*.
     * **www**, or **me**, or **teleport*&#x2A; — If you'd like to link to your subdomain &#x2A;(as mentioned in point 2 above)*.
     * Some providers ask for the full domain shown in SellApp instead of &#x2A;*@** or the subdomain prefix. If your DNS dashboard does that, use the exact value SellApp shows.
   * **Value**/&#x2A;*Points To:** sell-beacon.net
   <Note>
     Some DNS providers require a period at the end of the domain that's being pointed to. In which case, you'll want to enter: sell-beacon.net.
   </Note>

3. **TXT Record**

   * If SellApp shows a TXT record, add it exactly as displayed. This is usually an **\_acme-challenge** record used to issue SSL for your domain.
     * If you are linking a root domain
       * **Host/Name:** \_acme-challenge
       * **Value/Points To:** The random string of characters shown on the SellApp page
     * If you are linking a subdomain
       * **Host/Name:*&#x2A; **\_acme-challenge.www*&#x2A; or **\_acme-challenge.me*&#x2A; or **\_acme-challenge.teleport**
       * **Value/Points To:** The random string of characters shown on the SellApp page

   <Note>
     At times, the TXT record is not required, so if it doesn't appear in SellApp you should be OK to proceed with the rest of the setup steps.
   </Note>

Once done, let the page finish loading on SellApp. Usually this takes less than a few minutes once the above values have been set, however, with some providers it may take longer.

***

## **Support: My custom domain is not being verified** [#support-my-custom-domain-is-not-being-verified]

Please make sure your DNS records have the following values:

1. 1X CNAME value pointing from host \* to value **sell-beacon.net**
2. 1X CNAME value pointing from host &#x2A;*@** to value **sell-beacon.net** (**www**, or **me**, or **teleport** if it's a subdomain )
3. 1X TXT host pointing from just **\_acme-challenge*&#x2A; to value being the random string of characters shown on the SellApp page (**\_acme-challenge.www*&#x2A;, or **\_acme-challenge.me*&#x2A;, or **\_acme-challenge.teleport** in case of subdomain)

Once done, go to the SellApp side and let it finish loading. This should take a few minutes once the above has been completed.

Should things not finish loading on the SellApp side in an hour after the changes have been made, it might be an issue with your DNS provider. As a workaround, we advise switching from your current DNS provider to Cloudflare.

Switching is free and easy to do, and should take no more than 5 minutes.


# Post-Purchase Redirect (/docs/post-purchase-redirect)



You might need to redirect a customer to a URL of your choosing once they have made payment and completed their purchase.

With SellApp, you can do so as follows: create or edit the relevant product, navigate to the **Customization** section, then enter the URL in the **redirect URL** input field.

Once done and saved, customers will be redirected to the URL you've entered. If you've appended the URL with any dynamic variables, these will automatically be inserted before redirecting your customer.

***

## Dynamic Redirect Variables [#dynamic-redirect-variables]

At present, the following dynamic redirect variables are supported:

* `[customer_email]` The customer's email address
* `[order_id]` The order ID associated with the purchase
* `[quantity]` The quantity purchased for the first product in the order
* `[payment_method]` The payment method used for the order

Looking for a variable that's not in the above list? Send us a message by contacting us via live chat &#x2A;(found at the bottom right hand corner of this page)*

### Redirect Example [#redirect-example]

You have a coding course. You want to automatically check whether a customer has paid for your course before activating their account and displaying the course.

With redirect URLs and dynamic variables, you can verify whether the customer's order ID and email address correspond with a paid invoice. For example, you can check the API or store incoming webhook data from your `order completed` webhooks, then let the customer create an account or activate their existing account.

The redirect URL would be: `https://my-coding-course.com/purchase-completed?email=[customer_email]&orderId=[order_id]`


# Pre-Fill Checkout Info (/docs/pre-fill-info)



At times, you might want to pre-fill the product page with a customer's checkout information.

A good example is when you want to redirect a customer from your own project to the checkout page in order to reduce the risk of mistakes during checkout.

With SellApp, you can do so by appending the URL with the appropriate query string variables. This helps when you already know the buyer's email, product variant, quantity, coupon, or preferred payment method.

***

## Supported variables [#supported-variables]

At present, the following query string variables are supported:

* `coupon` Any coupon code you would like to have automatically applied
* `email` The customer's email address
* `payment_method` The payment method with which the customer will pay. For built-in methods, use the gateway value such as `STRIPE`, `PAYPAL`, `MERCADO_PAGO`, `MOLLIE`, `RAZORPAY`, `SQUARE`, `PADDLE`, `PAYSTACK`, `VENMO`, `AUTHNET`, `NMI`, or a crypto value such as `BTC`, `ETH`, or `SOL`. For custom payment methods, use the full custom method value shown by SellApp.
* `locale` or `lang` The hosted checkout language. Supported values include `en`, `de`, `fr`, `nl`, `es`, and `pt-BR`.
* `quantity` Product quantity which the customer will be purchasing
* `variant` If there is more than one variant, you can specify a specific variant ID
* `additional-[key]&#x60; The key and value of a checkout info field &#x2A;(you can copy the key when creating/editing a checkout info field)*

Looking for a variable that's not in the above list? Send us a message by contacting us via live chat &#x2A;(found at the bottom right hand corner of this page)*

### Checkout Example [#checkout-example]

Your website is all about rare game skins. Logged in customers can browse and purchase these game skins. One of your customers, John Doe, wants to purchase one of these skins and clicks on it to be redirected to the SellApp checkout page.

Rather than sending John to the default URL `https://example.sell.app/product/rare-game-skin` you could modify the URL with the customer's information you already have on your end.

Say they have a preferred payment method, are a recurring customer eligible for a 5% discount coupon, and they modified the quantity input to 2 rare game skins. Additionally, you have a custom checkout info "text" field that asks for the customer's in-game username.

You could then use this information and automatically modify the URL with the new query string variables.

The final URL would be: `https://example.sell.app/product/rare-game-skin?coupon=LOYAL5&email=john_doe@example.com&payment_method=STRIPE&quantity=2&locale=es&additional-4124bc0a9335c27f086f24ba207a4912=JohnDoe123`

***

## Embed modal variables [#embed-modal-variables]

The query string variables above apply to SellApp storefront and product URLs. If you are using the embed modal on your own site, pass the same kind of data on the button instead.

For standard checkout values, use `data-sell-*` attributes such as `data-sell-coupon`, `data-sell-email`, `data-sell-payment_method`, `data-sell-quantity`, `data-sell-variant`, and `data-sell-language`.

For custom checkout information fields, use `data-sell-checkout-{fieldKey}`. Copy the field key from SellApp; it is not always the same as the field label customers see at checkout.

```html
<button
  data-sell-store="123"
  data-sell-product="456"
  data-sell-email="john_doe@example.com"
  data-sell-coupon="LOYAL5"
  data-sell-quantity="2"
  data-sell-payment_method="STRIPE"
  data-sell-language="es"
  data-sell-checkout-4124bc0a9335c27f086f24ba207a4912="JohnDoe123"
>
  Buy now
</button>
```

Embed checkout field values are parsed as JSON when possible, so booleans, numbers, arrays, and objects can be passed when a field type needs them. See [Embed Digital Products](/embedding-products#checkout-info-prefills) for the full embed attribute list.


# Dynamic Webhook Setup (/docs/setting-up-dynamic-webhook)



SellApp's dynamic webhook sends a `POST` request to the webhook URL you enter on a product variant.

The `POST` request is sent as a `JSON object` when a customer successfully completes a payment, and contains all the relevant order data so your webhook can process the order programmatically.

Whatever value you return to us as a response to the above `POST` request can be passed along to the customer as the dynamic deliverable. Use dynamic webhooks when digital product delivery depends on your own system, such as generated accounts, custom keys, provisioning flows, or external stock.

<Warn>
  Use an `HTTPS` webhook endpoint in production so the order payload and signature cannot be intercepted.
</Warn>

***

## **Generate a webhook secret** [#generate-a-webhook-secret]

Before proceeding, we strongly advise creating a webhook secret that you'll want to be using to verify and validate incoming webhook requests as legitimate.

If you don't do so, a malicious person could spoof requests and make it look like we're sending them, thus possibly resulting in your stock being drained.

Here's how to create a webhook secret:

1. Navigate [to your store's developers settings](https://sell.app/dashboard/settings?settings=developers)
2. Click "Generate" in the "Webhook secret" section.
3. The newly generated secret is saved and copied to your clipboard.

***

## **Validating signed webhooks** [#validating-signed-webhooks]

To verify the authenticity of webhook calls sent to your dynamic webhook endpoint, SellApp sends a HMAC signature that is comprised of the JSON encoded request body and your generated webhook secret.

<Note>
  SellApp uses the 

  `sha256`

   hash function
</Note>

Here is a validation example for the dynamic webhook endpoint in PHP:

```php
$secret = "webhook-secret-here"; // the webhook secret you generated on SellApp
$signature = $_SERVER['HTTP_SIGNATURE']; // Retrieving the HMAC signature sent by our servers

$computedSignature = hash_hmac('sha256', file_get_contents('php://input'), $secret); // Validating the HMAC signature sent by our servers

if (hash_equals($computedSignature, $signature)) {
    // The signature sent by the webhook is valid, we can process the order
} else {  
  // The signature is invalid, this means something in the configuration is wrong or the webhook was not sent by SellApp
}
```

<Note>
  Sending a test dynamic webhook is only for the purpose of checking whether your endpoint is correct. The test sends mock data which is not representative for production webhooks.

  If you have set a webhook secret, test dynamic webhooks do send the secret in the header under the variable "signature"
</Note>

***

## **Returning dynamic content** [#returning-dynamic-content]

When your endpoint responds successfully, SellApp stores the response on the delivered order.

You can return plain text, which will be shown to the customer as the dynamic deliverable message. You can also return JSON with a `message` value:

```json
{
  "message": "Your custom account has been created."
}
```

If your dynamic webhook manages stock externally, you may also return a `stock` value to update the product variant's stock:

```json
{
  "message": "Your custom account has been created.",
  "stock": 42
}
```

Once this has been set up and configured correctly, you're all good to go.

Whenever a new order is delivered, we'll ping the dynamic endpoint URL you entered on the product variant, then pass along your webhook's response to the customer.


# SellApp FAQ (/docs/faq)



This page covers common SellApp questions that are not answered elsewhere in the documentation, including store settings, digital product stock, license keys, and order statuses.

## General [#general]

### How do I allow customers using a VPN to make purchases? [#how-do-i-allow-customers-using-a-vpn-to-make-purchases]

The VPN check helps protect your store from fraud. If you want to allow VPN-based purchases:

1. Open [your storefront payment settings](https://sell.app/dashboard/settings?settings=payment).
2. Enable **Allow VPN purchases**.
3. Save your changes.

### How do I change my subdomain? [#how-do-i-change-my-subdomain]

Store subdomains cannot currently be changed.

### How do I appeal negative feedback? [#how-do-i-appeal-negative-feedback]

Feedback cannot currently be appealed.

### My store got banned. Can I recover my products or data? [#my-store-got-banned-can-i-recover-my-products-or-data]

Storefronts that violate SellApp rules are reviewed and banned by the internal risk team. Associated products, files, and stock are purged. SellApp does not restore or redistribute that content.

## Products [#products]

### How do I restock my product? [#how-do-i-restock-my-product]

1. Open [the products dashboard](https://sell.app/dashboard/listings).
2. Click the relevant product.
3. Go to the **Content** section and add more stock.
4. Save the product.

### How do I sell serials, codes, keys, or licenses one-by-one? [#how-do-i-sell-serials-codes-keys-or-licenses-one-by-one]

1. Open [the products dashboard](https://sell.app/dashboard/listings).
2. Create a new product or edit an existing one.
3. In the **Content** section, select **Codes & Serials**.
4. Enter your stock in the **Saved Serials** field.
5. Set the correct stock delimiter if needed.
6. Save the product.

This is the recommended setup when you need license key management for software, access codes, gift codes, or any digital product that should deliver one unique value per order.

### How do I sell a product for under a dollar? [#how-do-i-sell-a-product-for-under-a-dollar]

Payment providers typically require the total order value to be at least one dollar. The usual workaround is to increase the minimum quantity so the total reaches that threshold.

For example, if a product costs `$0.50`, set the minimum quantity to `2`.

## Orders [#orders]

### When should I mark an order as completed, and how do I do so? [#when-should-i-mark-an-order-as-completed-and-how-do-i-do-so]

SellApp automatically detects successful payments and marks orders as completed. In most cases, you should not need to do this manually.

If you still need to mark an order as completed:

1. Open [the orders dashboard](https://sell.app/dashboard/invoices).
2. Click the three-dot menu on the relevant order.
3. Select &#x2A;*Mark as...**.
4. Choose **Mark as completed** and process the change.

### What do pending, voided, and completed mean in my orders dashboard? [#what-do-pending-voided-and-completed-mean-in-my-orders-dashboard]

* **Pending**: The order was started but not yet paid.
* **Voided**: The order was not paid within 24 hours.
* **Completed**: Payment was received and the order was processed successfully.


# SellApp Features (/docs/features)



Out of the box, SellApp includes the features merchants need to sell digital products online, automate delivery, manage payments, and grow a storefront without extra plugins.

## Digital Commerce Features [#digital-commerce-features]

* Digital product delivery with files, serials, license keys, manual delivery notes, and dynamic webhooks
* Hosted storefronts with custom domains, storefront personalization, Stories, feedback, and a visual builder
* Payment integrations for cards, wallets, direct crypto wallets, Solana, Crypto Tokens, Cash App, custom payment methods, and subscription-capable gateways
* Fraud protection, blacklists, VPN controls, checkout rate limiting, and store-level risk tooling
* Coupons, promotions, abandoned cart recovery, payment-method discounts or fees, bulk discounts, upsells, cross-sells, add-ons, and pay-what-you-want pricing
* Built-in affiliate programs with applications, invites, referral tracking, custom rates, coupons, and payout management
* Subscription and recurring billing support for products that need ongoing access
* Community access automation for Discord, Telegram, Slack, and WhatsApp
* Embedded checkout flows for selling from your own site
* Staff permissions, customer portals, tickets, order management, feedback replies, and analytics
* API access, webhooks, scoped API keys, webhook secrets, and recent webhook delivery logs

## What You Can Build [#what-you-can-build]

With SellApp, you can sell software, ebooks, memberships, license keys, subscriptions, paid communities, files, templates, videos, and other digital products through a single storefront.

## Built for Growth [#built-for-growth]

Start with a simple checkout and automated file delivery, then add the tools that match your sales strategy. You can use coupons and bundles for promotions, abandoned cart recovery for unfinished checkouts, upsells and cross-sells for larger carts, affiliate tracking for referrals, and tickets or feedback replies for customer support.

## Related Guides [#related-guides]

<Cards>
  <Card title="Setup Guide" href="/setup">
    Create your store, connect payments, and publish products.
  </Card>

  <Card title="Support" href="/support">
    Reach the support team when you need help with your store.
  </Card>

  <Card title="FAQ" href="/faq">
    Review common operational questions and answers.
  </Card>
</Cards>


# Sell Digital Products with SellApp (/docs)





SellApp is an ecommerce platform for selling digital products, downloads, subscriptions, license keys, and paid community access from one hosted storefront. You can launch a store, connect payment methods, automate delivery, and manage customers without stitching together separate tools.

<img src="`${docsBasePath}/images/dash.webp`" alt="SellApp dashboard" className="w-full rounded-xl border shadow-lg" />

## Start Selling Digital Products [#start-selling-digital-products]

Use these docs to move from account setup to your first paid order. The core flow is simple: create a storefront, connect a payment method, publish products, then let SellApp handle checkout, fraud checks, and digital product delivery.

## Getting Started [#getting-started]

SellApp is built for speed and simplicity, but it also supports larger workflows like subscriptions, affiliate programs, coupons, paid Discord or Telegram access, and custom payment methods. These pages cover the core setup flow, feature overview, support options, and common questions.

<Cards>
  <Card title="Setup Guide" href="/setup">
    Learn how to create your store, connect payments, and list your first products.
  </Card>

  <Card title="Store Settings" href="/storefront-settings-introduction">
    Configure dashboard defaults, checkout behavior, analytics, personalization, and developer tools.
  </Card>

  <Card title="Features" href="/features">
    Review the main platform capabilities available out of the box.
  </Card>

  <Card title="Support" href="/support">
    Find the fastest way to contact the SellApp support team.
  </Card>

  <Card title="FAQ" href="/faq">
    Read the answers to common questions from merchants using SellApp.
  </Card>
</Cards>


# Set Up Your SellApp Store (/docs/setup)





Starting to sell digital products on SellApp is simple. Most merchants can get through the initial store setup in a few minutes:

1. Sign up.
2. Create your first store.
3. List your products.

After that, customers can visit your store and make purchases while SellApp handles payment processing, digital delivery, and fraud protection.

## Signing Up [#signing-up]

Create an account in seconds at [sell.app/register](https://sell.app/register). You can register with email details or sign up in one click with Google.

## Creating a Storefront [#creating-a-storefront]

During sign-up, you can create a store immediately. We only ask for three pieces of information:

1. Store name
2. Store visibility
3. Store subdomain

<Callout title="Note">
  Store name and visibility can be updated later. Store subdomains cannot currently be changed.
</Callout>

<video className="w-full rounded-xl border">
  <source src="`${docsBasePath}/images/register.mp4`" type="video/mp4" />

  Your browser does not support the video tag.
</video>

## Listing Your Digital Products [#listing-your-digital-products]

Before listing products, connect at least one payment method in your storefront settings or directly at [the payment settings page](https://sell.app/dashboard/settings?settings=payment).

<Callout title="Note">
  Customer payments are sent directly to your linked payment account. SellApp does not hold your funds.
</Callout>

Once a payment method is connected, you can immediately start creating products. SellApp supports files, license keys, serials, subscriptions, memberships, and other digital product formats, so choose the delivery type that matches what customers should receive after checkout.

<video className="w-full rounded-xl border">
  <source src="`${docsBasePath}/images/product.mp4`" type="video/mp4" />

  Your browser does not support the video tag.
</video>

## Next Steps After Launch [#next-steps-after-launch]

You now have the basics in place: an account, a storefront, and your first products. From here, you can expand with more payment methods, a custom domain, promotions, paid community access, and automation.

<video className="w-full rounded-xl border">
  <source src="`${docsBasePath}/images/earn.mp4`" type="video/mp4" />

  Your browser does not support the video tag.
</video>

If you need help at any point, use the live chat button on the site.


# SellApp Support (/docs/support)



Should you ever need help with your SellApp store, the fastest way to contact SellApp is through live chat in the dashboard.

## Live Chat [#live-chat]

Live chat is the main support channel for creators who manage a storefront, products, payments, subscriptions, community access, or customer support tickets in SellApp.

### For Customers [#for-customers]

The SellApp support team cannot assist customers with purchase-related inquiries at this time. Please direct your questions to the store owner. You can do so through the contact options on the store URL itself or by creating a support ticket in the customer portal.

### For Creators [#for-creators]

To get in touch, navigate to [the SellApp dashboard](https://sell.app/dashboard) and click on the "Support" button at the bottom left. Then, select "Live Chat". The live chat button will appear at the bottom right of the page. Click it to open the live chat modal and start a chat session.

## Report Abuse [#report-abuse]

If you come across a storefront that appears to violate platform rules, send an email to [report@sell.app](mailto:report@sell.app) with the store URL, relevant details, and screenshots if possible.

<Callout type="warning" title="Important">
  Abuse reports are only handled through email. Do not send them through social media or live chat.
</Callout>


# Abandoned Cart Recovery (/docs/abandoned-cart-recovery)



Abandoned cart recovery helps you follow up with customers who start checkout but do not complete payment. SellApp can send reminder emails, limit reminders to certain order totals, and include a coupon incentive in a chosen email.

Open [Marketing settings](https://sell.app/dashboard/settings?settings=marketing), then use **Abandoned Cart Reminders**.

## Enable reminder emails [#enable-reminder-emails]

Switch **Status** on to enable abandoned cart reminder emails for the store. SellApp scans eligible unpaid checkouts and schedules reminders based on the settings you save.

Use the order amount range when you only want reminders for carts above a minimum total or below a maximum total. Leave the fields empty when every eligible cart should be considered.

## Configure the reminder schedule [#configure-the-reminder-schedule]

You can configure up to three reminder emails. Each reminder uses an hour delay after checkout starts, with a maximum of 72 hours.

The schedule cannot have gaps. Email #2 requires Email #1, and Email #3 requires Email #2. Each later reminder must be scheduled after the previous one.

## Add a purchase incentive [#add-a-purchase-incentive]

If you want to offer a discount, choose a coupon and select which reminder email should include it. The incentive is only shown when the order does not already have a coupon, and expired or unavailable coupons are ignored.

Use abandoned cart recovery with a clear coupon strategy. A small discount in Email #2 or Email #3 can recover buyers without training every customer to wait for a discount.


# Product Add-Ons (/docs/add-ons)



Product add-ons are optional extras customers can add while buying a digital product. They work well for priority support, setup help, extra files, license upgrades, templates, source files, or any small product that makes the main purchase more valuable.

***

## Create an add-on [#create-an-add-on]

Open [Add-ons](https://sell.app/dashboard/addons), then click **New add-on**.

Set the basics:

1. Add a title, slug, and description.
2. Choose the visibility.
3. Choose which parent products can offer this add-on.
4. Save the add-on.

An add-on is still a listing behind the scenes, but it is presented as an optional attachment to the parent product instead of as a normal storefront product.

***

## Attach add-ons from a product [#attach-add-ons-from-a-product]

You can also attach add-ons while editing a product.

Open the product, expand **Marketing**, then use **Add-ons** to select one or more add-ons customers can choose from.

Customers will see those add-ons during cart and checkout for that product. If they select one, SellApp stores the add-on alongside the parent order item so the relationship stays clear on the order.

<Note>
  Add-ons are built for one-time product carts. They are not available for subscription carts.
</Note>

***

## Good add-on ideas [#good-add-on-ideas]

Strong add-ons are easy to understand and clearly tied to the main product. A good add-on should feel like a natural upgrade, not a separate product the customer has to research.

Examples:

1. Installation help for a software product.
2. A commercial license upgrade for a digital asset.
3. Bonus templates for a design pack.
4. Priority support for a setup-heavy product.
5. Source files for a finished resource.

Keep the add-on title direct. Customers should understand the upgrade before they even open the description.


# Product Bundles (/docs/bundles)



Product bundles let you sell multiple products together as a single listing. They are useful for starter packs, full-access drops, course packs, template bundles, software packs, and discounted digital product collections.

***

## Create a bundle [#create-a-bundle]

Open [Bundles](https://sell.app/dashboard/bundles), then click **New bundle**.

Set up the bundle like a normal listing:

1. Add a title, slug, and description.
2. Choose the visibility.
3. Add product images.
4. Add any extra checkout fields, redirect URL, video, FAQ, or SEO fields you need.
5. Save the bundle.

After the bundle exists, add the products and variants it should include. Each bundle item can have its own quantity, so one bundle can include multiple copies of the same underlying item if needed.

<Note>
  Bundles are their own listings. Customers buy the bundle directly instead of adding the bundle itself into a normal cart flow.
</Note>

***

## Add products to a bundle [#add-products-to-a-bundle]

From the bundle editor, add the product variants that should be delivered when the bundle is purchased.

Use clear bundle titles so customers understand the package at a glance, then use the description to explain the included products and why buying the bundle is better than buying each product separately.

Strong bundle pages usually mention the full contents, the normal individual value, and the outcome the customer gets by buying everything together.

***

## Price the bundle [#price-the-bundle]

A bundle has its own pricing. Set the bundle price based on the value of the full package, not just the cheapest item inside it.

Common approaches:

1. **Discounted pack:** bundle several products and price below the sum of individual prices.
2. **Premium pack:** include exclusive files, access, or services that are not available separately.
3. **Fast-start pack:** combine the product with templates, guides, or support to shorten setup time.

Bundles currently work best for one-time purchases. If you need recurring billing, create a subscription product instead.

***

## Delivery [#delivery]

When a customer purchases a bundle, SellApp keeps a snapshot of the bundled items for that order. That means the order stays clear even if you edit the bundle later.

Use the order page to confirm which products were included in the customer's bundle purchase.


# Coupon Codes (/docs/coupons)



Coupons are code-based discounts for your SellApp storefront. They are best when you want a specific audience to enter a code, such as an affiliate audience, a private group, a returning customer segment, or a one-off support gesture.

***

## Create a coupon [#create-a-coupon]

Open [Coupons](https://sell.app/dashboard/coupons), then click **New coupon**.

Set the core fields:

1. Enter the coupon code customers will type at checkout.
2. Choose **Fixed amount** or **Percentage**.
3. Enter the discount amount.
4. Decide whether the coupon is store-wide or limited to selected products.
5. Optionally add a redemption limit.
6. Optionally set an expiration date and time.

Percentage coupons can also have a maximum discount amount. Use that when you want a large percentage discount to feel strong without risking a huge discount on high-ticket orders.

***

## Limit a coupon to products and variants [#limit-a-coupon-to-products-and-variants]

Turn off store-wide use when a code should only work on specific products. Then add the products that should accept the coupon.

For each selected product, choose one of these scopes:

1. **All variants, including ones added later** applies the coupon to every current and future variant of that product.
2. **Only selected variants** limits the coupon to the variants you check.

Use variant targeting when different plans, editions, or pricing options under the same product should have different discounts. A coupon rejected for one variant can still be valid for another selected variant of the same product.

This is useful for:

1. New product launches.
2. Slow-moving products.
3. Affiliate campaigns around a specific offer.
4. Private customer upgrades.
5. Support credits for a specific replacement purchase.

If a coupon should work everywhere, keep it store-wide and avoid extra product restrictions.

Product- and variant-limited coupon codes are useful when one offer needs a launch discount but the rest of your catalog should keep its normal pricing.

***

## Minimum amount and caps [#minimum-amount-and-caps]

Use **Minimum amount** when the customer should spend a certain amount before the coupon applies.

Use **Maximum discount amount** for percentage coupons when you want to cap the money saved. For example, a 50% code with a maximum discount of $25 still feels generous, but it will not remove half the price of a high-value cart.

***

## Coupons vs promotions [#coupons-vs-promotions]

Use a coupon when the customer needs a code.

Use a promotion when the discount should apply automatically.

If a cart has both a coupon and a promotion, the promotion's stackable setting decides whether the automatic promotion can apply alongside the coupon.


# Marketing Digital Products (/docs/marketing-introduction)



SellApp's marketing tools help you shape how customers discover digital products, choose a better option, and add more before checkout. Use them to launch offers, raise average order value, reward campaigns, and guide buyers through a larger catalog.

The main tools are:

1. **Promotions** for automatic store-wide offers with phases, limits, and checkout labels.
2. **Abandoned cart recovery** for reminder emails, order amount ranges, schedules, and coupon incentives.
3. **Coupons** for code-based discounts that can apply store-wide or to selected products.
4. **Bundles** for selling multiple products together as one listing.
5. **Add-ons** for optional extras customers can attach in the cart or checkout.
6. **Upsells and cross-sells** for recommending variants and similar products on product pages.
7. **Stories** for visual product drops, previews, social proof, and builder blocks.

***

## Where to start [#where-to-start]

Use **Promotions** when you want the discount to apply automatically.

Use **Abandoned cart recovery** when customers start checkout but do not complete payment.

Use **Coupons** when you want customers, affiliates, or campaigns to use a specific code.

Use **Bundles** when the offer is a packaged product with its own listing page, such as a template pack, software bundle, course pack, or digital download collection.

Use **Add-ons** when the extra should be optional during purchase.

Use **Upsells and cross-sells** when the customer is already viewing a product and you want to guide them to a better or related option.

***

## A simple launch stack [#a-simple-launch-stack]

For a product launch, you might:

1. Create a limited-time promotion for launch pricing.
2. Enable abandoned cart recovery with a follow-up email and optional coupon.
3. Create a bundle that packages the main product with bonus products.
4. Add a premium add-on for customers who want extra setup, support, or files.
5. Mark the strongest variant as **Recommended** or **Best value**.
6. Publish a story that shows the product, bonus, or customer proof in the storefront builder.

Each tool can work on its own, but they become stronger when they point customers toward the same offer.


# Automatic Promotions (/docs/promotions)



Promotions are automatic discounts for your SellApp storefront. Customers do not enter a code; SellApp checks the current active promotion and applies it at checkout when the order qualifies.

Use promotions for digital product launches, flash sales, limited redemption offers, cart incentives, and scheduled campaigns.

***

## Create a promotion [#create-a-promotion]

Open [Promotions](https://sell.app/dashboard/promotions), then click **New promotion**.

Set the basics first:

1. Add a clear internal name, like `Launch week` or `Weekend flash sale`.
2. Choose whether the promotion is active.
3. Optionally set a start date and end date.
4. Set a priority. Lower numbers are evaluated first when multiple promotions are active.
5. Decide whether the promotion can stack with coupons.
6. Optionally cap total redemptions.

After that, configure at least one phase.

***

## Promotion phases [#promotion-phases]

Phases let one promotion change over time or after a usage cap. Each phase can have:

1. A percentage or fixed discount.
2. An optional end date.
3. An optional maximum redemption count.
4. An optional minimum subtotal.

For example, a launch promotion can start at 30% off for the first 50 orders, then move to 15% off until the campaign ends. This lets a product launch reward early buyers without requiring a separate coupon code.

<Note>
  If a customer has a valid coupon and the promotion is not stackable, SellApp will block the promotion for that cart. Turn on stacking only when you intentionally want both discounts to apply.
</Note>

***

## Storefront labels and incentives [#storefront-labels-and-incentives]

SellApp can show promotion labels on the storefront, cart, and embed modal. If a promotion has a minimum subtotal, the cart and embed modal can show an incentive message such as how much more the customer needs to add before the deal unlocks.

Keep promotion names customer-friendly if you plan to show them publicly. `Summer drop` reads better than `promo-test-4`.

***

## Check performance [#check-performance]

The Promotions dashboard includes usage data, so you can see whether a campaign is getting redeemed. If a promotion is not being applied, check:

1. The promotion status.
2. Start and end dates.
3. Promotion and phase redemption caps.
4. Minimum subtotal.
5. Coupon stacking.
6. Whether another active promotion has higher priority.


# Rewards (/docs/rewards)



Rewards let you recognize customers based on their store activity. You can create rules that grant coupons, wallet credit, badges, status labels, or display-only recognition when customers reach configured milestones.

Open [Rewards](https://sell.app/dashboard/rewards) to create and manage reward rules.

***

## Reward rules [#reward-rules]

A reward rule defines when a customer earns something and what SellApp should issue. Rules can be active for a specific date range and can be configured to fire once per customer.

When creating a rule, choose:

1. The trigger that determines when the reward is earned.
2. The threshold the customer must reach.
3. The output the customer receives.
4. Whether the rule is active and visible.

***

## Reward outputs [#reward-outputs]

Rewards can issue different output types:

1. **Coupons** for discounts customers can redeem later.
2. **Wallet credit** for store credit that appears in the customer wallet.
3. **Badges** and **status labels** for recognition.
4. **Display rewards** for customer-visible milestones that do not issue money or coupons.

Coupon rewards can be scoped to specific products and can include expiration behavior. Wallet credit rewards require customer wallets to be available for the store.

***

## Customer portal [#customer-portal]

Customers can view earned rewards and progress from the customer portal. Wallet-credit rewards link back to the wallet history so customers can see the credit entry.

The [reward grants](https://sell.app/dashboard/rewards/grants) view shows issued rewards, their source rule, the customer, and the output that was granted.

***

## Reversals [#reversals]

If an order is refunded or voided, SellApp can revoke related reward grants and release redeemed reward coupons where appropriate. Review reward grants after refunds when you need to confirm a customer's current reward state.


# Storefront Stories (/docs/stories)





Stories help turn your store into a more interactive buying experience without forcing customers to bounce around your storefront. Use them for product launches, social proof, quick demos, product education, bonus previews, and visual merchandizing for digital products.

<img src="`${docsBasePath}/images/stories.png`" alt="Story example" className="rounded-xl w-full shadow-lg" />

Instead of browsing various pages, customers can:

1. Open a story to view an image/video about a product being used
2. Click on a product link **directly within the story*&#x2A; to immediately navigate to the product page &#x2A;(or display the product's embed modal)*
3. Do the same as above for various other stories. You can have a story for your products, customer reviews, upcoming product drops, and so on

***

## Creating Stories [#creating-stories]

<img src="`${docsBasePath}/images/stories-dashboard.png`" alt="Stories in Dashboard" className="rounded-xl w-full shadow-lg" />

1. Navigate to [the Stories dashboard by clicking here](https://sell.app/dashboard/stories).
2. Click on the "New Story" button to create your first story
3. Add a title, choose whether the story is public or hidden, then upload up to 30 media files. Each media file:
   1. Will be played one after the other
   2. Can be linked to a unique product
   3. Can have a different "Call to action" text
4. You can preview the story before publishing it
5. You can sort media files to your liking, the story will play the media in the order you've sorted
6. You can also sort each story to your liking. The order in which you sort a story will be shown when you create the Stories block in the builder.

That's it. You've now created one or multiple Stories. Now, head to the builder to display your Stories block.

***

## Displaying Stories [#displaying-stories]

<img src="`${docsBasePath}/images/stories-builder.png`" alt="Stories in Builder" className="rounded-xl w-full shadow-lg" />

1. Navigate to [the storefront builder by clicking here](https://builder.sell.app).
2. Click on the relevant section within which you want to add the "Stories" block
3. Click the "Add block" button in the left sidebar, then select the "Stories" option
4. The "Stories" block will be inserted into the section. Drag and drop it to whichever place you prefer, the whole section is your canvas. &#x2A;(Don't forget to check the mobile version of your page once done)*
5. If required, you can configure which story/stories to display by clicking on the "Stories" block and doing so in the left sidebar's "Stories Settings"

Once done, click the "Publish" button at the top right to publish your store's changes. You can then visit your site to see the stories block and interact with it.


# Upsells and Cross-Sells (/docs/upsells-cross-sells)



Upsells and cross-sells help customers choose a better option without making them hunt around your digital product store.

In SellApp, these live inside the product editor under **Marketing**.

***

## Featured variants [#featured-variants]

A featured variant highlights one variant on the product page as the recommended choice.

Open a product, expand **Marketing**, then choose a **Featured variant**. You can label it:

1. **Popular**
2. **Recommended**
3. **Best value**

Use this when one variant is the offer you most want customers to pick, like a lifetime plan, premium pack, larger quantity, bundled license, or best-margin option.

<Note>
  Featured variants are product-level recommendations. They point customers toward a variant of the product they are already viewing.
</Note>

***

## Similar products [#similar-products]

Similar products are cross-sells. They recommend products from elsewhere in your store alongside the current product.

Open a product, expand **Marketing**, then choose **Similar products**. If a product has multiple variants, choose the exact variant you want to recommend.

Use similar products for:

1. Products that solve the next problem.
2. Companion templates or files.
3. A cheaper starter product.
4. A higher-value product for customers who want more.
5. Product families that naturally belong together.

***

## Keep recommendations tight [#keep-recommendations-tight]

Do not recommend everything. Two or three strong cross-sells usually convert better than a long list of loosely related products.

Use the featured variant to guide the current product decision, then use similar products when the customer may want something adjacent.

If the extra should be attached to the same cart item, use [Add-ons](/add-ons) instead.


# Store Blacklist (/docs/blacklist)



The Blacklist helps you reduce fraud and abuse before it reaches checkout. Use it to block customers or traffic patterns that should not be allowed to buy from your store.

Open [Blacklist](https://sell.app/dashboard/blacklist) to manage entries.

***

## Blacklist types [#blacklist-types]

SellApp supports these blacklist types:

1. **Email** for a specific email address.
2. **Wildcard email** for a pattern across multiple emails.
3. **IP** for a specific IP address.
4. **Country** for country-level blocking.
5. **ASN** for blocking a network or hosting provider range.

Each entry also includes a description. Write the reason clearly so another team member understands why the block exists later.

***

## When to add an entry [#when-to-add-an-entry]

Add a blacklist entry when you see repeated fraud attempts, abuse, chargeback patterns, spam tickets, bot traffic, or traffic from a source that should never purchase.

Avoid overly broad blocks unless the risk is clear. A country or ASN block can stop legitimate customers too, so use specific email or IP blocks when the issue is narrow.

***

## Review periodically [#review-periodically]

Blacklist entries can outlive the original issue. Review older entries from time to time, especially broad wildcard, country, and ASN blocks.

If a real customer says they cannot checkout, check the Blacklist before assuming the payment method is failing. This can save time when troubleshooting blocked payments or failed purchase attempts.


# Payment Charges (/docs/charges)



Charges are standalone payment records. They are useful when you need to request a payment that is not tied to a normal storefront product flow, such as a custom invoice, service fee, balance collection, or manual deal.

Open [Charges](https://sell.app/dashboard/charges) to view them.

***

## What a charge includes [#what-a-charge-includes]

A charge can store:

1. Customer email.
2. Reference text.
3. Status.
4. Checkout URL.
5. Payment method and gateway data.
6. Currency and totals.
7. VAT and fee data.
8. Description, deliverable data, metadata, webhook, return URL, and cancel URL.

Use the reference field to make charges easy to recognize later.

***

## Charge statuses [#charge-statuses]

The Charges dashboard shows status, customer, revenue, and payment method. You can search by charge ID.

Pending or voided charges can be marked from the dashboard when the charge flow requires a manual status update. For higher-risk or larger flows, review the charge details before marking it completed.

***

## Charge analytics [#charge-analytics]

The top of the Charges dashboard summarizes revenue and completed charge count for the selected date range. Choose **Revenue** or **Orders** to switch the chart.

Each metric includes the previous period for comparison and shows whether the result increased or decreased. Available date presets include today, the last 7 days, last month, last quarter, last year, this month, all time, and a custom range.

Charge analytics only include standalone charges. Product purchases remain in the main order and dashboard analytics.

***

## When to use charges [#when-to-use-charges]

Use charges when the customer should pay a specific amount without browsing a public product page. They can help with manual payment flows, custom work, one-off services, or payment links that should not become reusable storefront products.

Use products when the offer should be discoverable, reusable, and part of the normal storefront catalog.


# Customer Wallets (/docs/customer-wallets)



Customer wallets let you keep store credit close to the customer account. Customers can top up a wallet, spend available balance at checkout, and review wallet activity from the customer portal.

Open [Wallet](https://sell.app/dashboard/wallet) to manage wallet settings.

***

## What wallets are for [#what-wallets-are-for]

Wallets work well when you want to:

1. Let returning customers keep a prepaid balance.
2. Issue store credit after a support resolution.
3. Reward customers with wallet credit.
4. Offer checkout incentives such as cashback or top-up bonuses.

***

## Enable wallet checkout [#enable-wallet-checkout]

From the Wallet dashboard, configure whether wallet checkout is available for the store. You can also configure minimum and maximum top-up amounts, expiration behavior, and the payment methods customers can use when adding funds.

When wallet checkout is enabled, eligible customers can authenticate during checkout. If the available wallet balance fully covers the order, SellApp can complete the checkout without requiring another payment method. If the wallet covers only part of the order, the customer chooses a payment method for the remaining balance.

Wallet checkout is intended for one-time purchases. Subscription purchases can currently not be paid for with wallet checkout.

***

## Wallet history and adjustments [#wallet-history-and-adjustments]

Each wallet has a ledger history. Ledger entries can include top-ups, checkout spend, cashback, and so on.

Use the customer detail page when you need to review a customer's wallet, make a manual adjustment, freeze wallet activity, or inspect the history behind a balance.

***

## Incentives [#incentives]

Wallet incentives are configured from the Wallet area:

1. [Bonus tiers](https://sell.app/dashboard/wallet/bonus-tiers) let you add extra credit when customers top up above configured thresholds.
2. [Cashback rules](https://sell.app/dashboard/wallet/cashback-rules) let you return a percentage of eligible purchases as wallet credit.

Cashback and bonus credit appear in the customer wallet history, so customers can see where each credit came from.


# Feedback (/docs/feedback)



Feedback helps you keep customer sentiment close to the orders and products that created it.

***

## Feedback [#feedback]

Open [Feedback](https://sell.app/dashboard/feedback) to review customer ratings and messages.

You can search feedback, filter by star rating, sort the table, and jump back to the related order when you need more context.

Feedback is tied to the product, variant, and order when available, so it can help you spot issues like unclear digital delivery text, bad stock, confusing checkout fields, or products that need better setup instructions.

***

## Turn feedback into action [#turn-feedback-into-action]

Use feedback patterns to improve your store:

1. Repeated delivery confusion means the product instructions need work.
2. Repeated support conversations about the same issue may need an FAQ.
3. Positive feedback can become a story, testimonial, or storefront proof.
4. Low ratings on one variant may mean the offer or product copy is misaligned.


# Orders and Customers (/docs/orders-and-customers)



The Orders and Customers dashboards are where you handle completed purchases, failed digital delivery, customer history, and sales exports.

***

## Orders [#orders]

Open [Orders](https://sell.app/dashboard/invoices) to search and review purchases.

You can search by:

1. Order ID or customer email.
2. Transaction ID.
3. Crypto transaction hash or address.
4. Coupon code.
5. Product name.
6. Serial code.
7. Additional information.
8. Discord customer data.

Use status and payment filters when you need to narrow the list quickly.

***

## Order actions [#order-actions]

From an order, you can inspect payment, customer, product, delivery, community access, and custom payment proof details.

If fulfillment failed, retry delivery from the order. SellApp will only retry affected delivery steps, so you can recover from temporary webhook, stock, license key, community access, or notification issues without recreating the whole order.

For custom payment methods, orders can require review before they are marked completed.

***

## Customers [#customers]

Open [Customers](https://sell.app/dashboard/customers) to search customer emails and review revenue per customer.

The customer slide-over helps you understand what someone bought, how much revenue they generated, and where you may need to support them. This is useful when a buyer asks about an order, a license key, a subscription, or access to a paid community.

***

## Exports [#exports]

Use sales and customer exports when you need reporting outside SellApp. Exports are useful for accounting, cohort analysis, campaign review, or reconciling activity with an external CRM.


# Resolution Center (/docs/resolution-center)



The Resolution Center is the dashboard workspace for customer support. It replaces the older ticket view with a support queue, richer customer context, reply templates, and more.

Open [Resolution Center](https://sell.app/dashboard/resolution-center) to manage support conversations.

***

## Support queue [#support-queue]

The support queue shows customer conversations for the current store. Tickets can be tied to an order, but they can also be general support requests when the customer does not have an order reference.

Use each ticket view to:

1. Read the full conversation thread.
2. Reply to the customer.
3. See related order and customer context when available.
4. Close, reopen, archive, or unarchive a conversation.
5. Apply supported resolution actions.

Customers can manage their own conversations from the customer portal under Support.

***

## Reasons and templates [#reasons-and-templates]

[Support reasons](https://sell.app/dashboard/resolution-center/reasons) help categorize requests. You can use them to guide the customer when they create a ticket and to route common issues into clearer support workflows.

[Response templates](https://sell.app/dashboard/resolution-center/templates) help staff reply consistently to repeated questions. Templates can include placeholders for customer, order, refund, and wallet context.

***

## Automation [#automation]

[Support automation](https://sell.app/dashboard/resolution-center/automation) lets you create auto-response rules for common scenarios. Rules can match request details such as reason, products, and refund limits, then send a response or perform a supported resolution action.

Keep automated actions narrow. Review the daily refund and wallet-credit limits before enabling rules that can move money.

***

## Reporting [#reporting]

Use the [resolution report](https://sell.app/dashboard/resolution-center/report) to monitor support outcomes. The report helps you see how tickets are being resolved and whether support patterns point to product, delivery, payment, or checkout issues that need attention.


# Authorize.net Payments (/docs/authorize)



[Authorize.net](https://www.authorize.net/) is a card payment processor that lets customers pay with their credit or debit card.

SellApp has integrated Authorize.net as a payment processor, helping you accept card payments through Authorize.net for your digital products via the SellApp storefront and API. Use it when you already process cards through Authorize.net and want SellApp to handle checkout, order tracking, and delivery.

***

## Link Authorize.net to SellApp [#link-authorizenet-to-sellapp]

1. Navigate to [your storefront payment settings by clicking here](https://sell.app/dashboard/settings?settings=payment).
2. Click "Card (Authorize.net)". In the modal that appears, enter the requested credentials:
   1. You were provided your "API Login ID" and "Transaction Key" when first signing up to Authorize.net
   2. Generate a "Signature Key" by logging into the [Merchant Interface](https://login.authorize.net/) -> Click the "Account" tab -> click "API Credentials & Keys" in the "Security Settings" section
      * Finally, create the "Signature Key" and enter it on the SellApp side
      * This page also shows your API Login ID and optionally lets you create a new "Transaction Key"
3. Optionally add a discount/fee if you want to adjust the checkout total for customers who pay with Authorize.net.
4. Save the settings. If all details were entered correctly, you'll now see "Card (Authorize.net)" as "Active" in the payment settings.

All done. Authorize.net has been enabled for your store and you can now enable Authorize.net for every new product you create.

***

## Optionally: Enabling Authorize.net for products that already exist [#optionally-enabling-authorizenet-for-products-that-already-exist]

If you want to enable Authorize.net for products that already exist, here's how to do so:

1. Navigate to [your products dashboard by clicking here](https://sell.app/dashboard/listings).
2. On the products page, toggle the checkboxes of the products you want to enable Authorize.net for.
3. Open the "Bulk update" dropdown and click "Payment methods".
   * A modal will pop up; check "Card (Authorize.net)" &#x2A;(& optionally other payment methods you'd like enabled)*
4. Finally, click "Update All" in the modal to update the products' payment methods.

That's all done for you: all the products you selected will now have Authorize.net enabled as a payment method, which customers will be able to select when making a purchase.


# Cash App Payments (/docs/cashapp)





[Cash App](https://cash.app/) is a P2P payment service that lets users transfer money to one another via a mobile app.

SellApp has integrated Cash App as a payment processor, which means you can accept Cash App payments for your digital products through the SellApp storefront and API. The key setup step is email forwarding, which lets SellApp detect eligible Cash App receipts and process orders automatically.

***

## Step 1: Link email [#step-1-link-email]

The first step is to add an email address to your Cash App account if you haven't done so already:

1. [Sign in to Cash App on your computer](https://cash.app/account/activity)

<img src="`${docsBasePath}/images/cashapp/account_step.png`" alt="SellApp Dashboard" className="rounded-xl w-1/2 mx-auto shadow-lg dark:shadow-black" />

2. [Go to your account settings](https://cash.app/account/settings)

<img src="`${docsBasePath}/images/cashapp/email_step.png`" alt="SellApp Dashboard" className="rounded-xl w-1/2 mx-auto shadow-lg dark:shadow-black" />

3. In the "Personal info" section, you should see your email address
4. If it's not there, click the "add" button and follow the steps to enter your personal email address
   * *Don't forget to verify your email with the code Cash App sends you*

***

## Step 2: Forward Cash App emails to SellApp [#step-2-forward-cash-app-emails-to-sellapp]

<Warn>
  Without the forwarding rule added, SellApp cannot detect or process Cash App payments automatically, so make sure to add it.
</Warn>

Here's how to do so with a `@gmail.com` email address:

1. [Click here to open your gmail settings](https://mail.google.com/mail/u/0/#settings/general).
2. Click the "Forwarding and POP/IMAP" tab &#x2A;(the 6th tab at the top)*

<img src="`${docsBasePath}/images/cashapp/tab_step.png`" alt="SellApp Dashboard" className="rounded-xl w-1/2 mx-auto shadow-lg dark:shadow-black" />

3. Click the "Add a forwarding address" button
4. In the modal that appears, enter `<cash@payments.sell.app>` as the forwarding address

<img src="`${docsBasePath}/images/cashapp/forwarding_step.png`" alt="SellApp Dashboard" className="rounded-xl w-1/2 mx-auto shadow-lg dark:shadow-black" />

5. Once you click the "Next" button, Gmail will send our systems an email with a confirmation URL. We automatically forward the URL to your email. Visit this URL and you will be good to go.
6. Once verified, we need to create a filter to only forward emails from Cash App to the email we just linked:

   1. In Gmail, [go to the "Forwarding" section by clicking here](https://mail.google.com/mail/u/0/#settings/fwdandpop)

   <img src="`${docsBasePath}/images/cashapp/filter_step.png`" alt="SellApp Dashboard" className="rounded-xl w-1/2 mx-auto shadow-lg dark:shadow-black" />

   2. Click the blue "creating a filter!" text to open the filter modal
   3. In the filter modal that pops up, enter `<cash@square.com>` in the "From" field, then click the "Create filter" button

   <img src="`${docsBasePath}/images/cashapp/from_step.png`" alt="SellApp Dashboard" className="rounded-xl w-1/2 mx-auto shadow-lg dark:shadow-black" />

   4. In the next page, select the "Forward it to" option, and select `<cash@payments.sell.app>` as the forwarding address

   <img src="`${docsBasePath}/images/cashapp/to_step.png`" alt="SellApp Dashboard" className="rounded-xl w-1/2 mx-auto shadow-lg dark:shadow-black" />

   5. Finally, click "Create filter"

If your Cash App receipt emails come from an `@notifications.cash.app` address instead, add that sender to your forwarding filter too. The goal is simple: Cash App receipt emails should forward to SellApp, but the rest of your inbox should not.

***

## Step 3: Link Cash App to SellApp [#step-3-link-cash-app-to-sellapp]

The final step is to add your Cash App details to your SellApp storefront:

1. Navigate to [your storefront payment settings by clicking here](https://sell.app/dashboard/settings?settings=payment).
2. Click Cash App. In the modal that appears, enter your Cash Tag &#x2A;(including the `$`)* and **the email address you added to your Cash App in step 1**.
3. Follow the forwarding step in the modal, confirm your information, then click "Finish". If all details were entered correctly, you'll now see Cash App as "Active" in the payment settings.

All done. Cash App has been enabled for your store and you can now enable Cash App for every new product you create.

***

## Optionally: Enabling Cash App for products that already exist [#optionally-enabling-cash-app-for-products-that-already-exist]

If you want to enable Cash App for products that already exist, here's how to do so:

1. Navigate to [your products dashboard by clicking here](https://sell.app/dashboard/listings).
2. On the products page, toggle the checkboxes of the products you want to enable Cash App for.
3. Open the "Bulk update" dropdown and click "Payment methods".
   * A modal will pop up; check Cash App &#x2A;(& optionally other payment methods you'd like enabled)*
4. Finally, click "Update All" in the modal to update the products' payment methods.

That's all done for you: all the products you selected will now have Cash App enabled as a payment method, which customers will be able to select when making a purchase.


# Custom Payment Methods (/docs/custom-payment-methods)



Custom Payment Methods let you accept payments through your own manual or external process while still tracking the order inside SellApp. They are useful when your preferred local wallet, bank transfer, private processor, or manual crypto flow is not available as a native integration.

Use them for any payment process where SellApp should create a pending order for you to verify before digital product delivery is completed.

***

## Create a custom processor [#create-a-custom-processor]

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **Custom Processors** and click **Add method**.

Choose one of two processor flows:

1. **Instruction-based:** SellApp shows payment instructions on checkout.
2. **Redirect-based:** SellApp sends the customer to your own payment page.

Then add the payment method name, optional description, optional icon, and the details for that flow.

***

## Instruction-based methods [#instruction-based-methods]

Use instruction-based methods when the customer should read payment details on the SellApp checkout page.

You can add:

1. A short description.
2. Rich instructions.
3. Up to three checkout steps.
4. Proof of payment upload.
5. A customer preview before saving.

If proof is required, the customer can submit text or a screenshot. The order will stay pending until you review it.

***

## Redirect-based methods [#redirect-based-methods]

Use redirect-based methods when you already have a hosted payment page.

Add a short description, then add a redirect URL and include variables when your external flow needs order context. SellApp supports variables like:

1. `{id}`
2. `{invoice_id}`
3. `{customer_email}`
4. `{currency}`
5. `{price}`
6. `{price_usd}`
7. `{product_name}`
8. `{quantity}`
9. `{return_url}`

For example, your redirect URL might include the order ID and price so your external page can prefill the checkout. Use `{return_url}` when your external payment page should send the customer back to the signed SellApp order checkout page.

***

## Enable on products [#enable-on-products]

When saving a custom processor, you can enable it on all current products. You can also control custom payment methods per variant from the product editor.

Custom processor orders require manual review. Open the order, confirm payment, then mark it completed when the payment is valid. Keep the instructions clear so customers know exactly where to pay, what proof to upload, and when they should expect their order to be reviewed.


# Mercado Pago Payments (/docs/mercado-pago)



Mercado Pago lets you accept supported one-time payments through your own Mercado Pago account while SellApp manages checkout, order tracking, and delivery.

***

## Add Mercado Pago [#add-mercado-pago]

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **Mercado Pago**.

Enter:

1. Public key.
2. Access token.
3. Webhook secret.

Then copy the SellApp webhook URL into your Mercado Pago application, enable the Payments event, and save the method in SellApp.

<Note>
  Mercado Pago webhooks must be configured in Mercado Pago Developers for your application. SellApp validates credentials when you save, but the webhook secret can only be fully verified when Mercado Pago sends a signed notification.
</Note>

***

## Enable Mercado Pago on products [#enable-mercado-pago-on-products]

When adding Mercado Pago, you can enable it for all existing products. You can also manage payment methods per variant from the product editor or with the Products dashboard bulk payment-method update.

Only products with compatible currencies and an active Mercado Pago setup will show Mercado Pago at checkout.

***

## Fees or discounts [#fees-or-discounts]

Once Mercado Pago is active, you can add a payment-method fee or discount.

Use a positive value to discount Mercado Pago payments. Use a negative value to add a fee.


# Mollie Payments (/docs/mollie)



Mollie lets you accept supported one-time payments through your own Mollie account while SellApp manages checkout, order tracking, and delivery.

***

## Add Mollie [#add-mollie]

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **Mollie**.

Enter your Mollie API key, then save the method. You can find the key in Mollie Dashboard > Developers > API keys.

SellApp validates the key with Mollie before saving. In production, use a live Mollie API key.

***

## Enable Mollie on products [#enable-mollie-on-products]

When adding Mollie, you can enable it for all existing products. You can also manage payment methods per variant from the product editor or with the Products dashboard bulk payment-method update.

Only products with currencies supported by Mollie will show Mollie at checkout.

<Note>
  Mollie currently supports one-time payments in SellApp. Subscriptions and refunds should be handled with another supported payment method for now.
</Note>

***

## Fees or discounts [#fees-or-discounts]

Once Mollie is active, you can add a payment-method fee or discount.

Use a positive value to discount Mollie payments. Use a negative value to add a fee.


# NMI Payment Gateway Setup (/docs/nmi)



NMI lets you accept debit and credit card payments for digital products through your own NMI payment gateway account. Connect NMI when you want card checkout handled through your merchant account while SellApp manages the order, delivery, and product-level payment settings.

***

## Add NMI [#add-nmi]

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **NMI**.

Enter:

1. Merchant secure key.
2. Merchant tokenization key.
3. Webhook signing key.
4. At least one supported currency.

Then save the method.

<Note>
  NMI credentials must match the expected key formats. If SellApp rejects a key, copy it again from your NMI account and make sure there are no extra spaces.
</Note>

***

## Enable NMI on products [#enable-nmi-on-products]

When adding NMI, you can enable it for all existing products. You can also manage payment methods per variant from the product editor or with the Products dashboard bulk payment-method update.

Use product-level controls when only certain listings should accept NMI card payments. For example, you might keep NMI enabled on high-volume digital downloads while leaving another payment method on subscription or manual-review products.

After NMI is removed, SellApp removes unavailable payment methods from variants so customers are not offered a broken checkout option.

***

## Fees or discounts [#fees-or-discounts]

Once NMI is active, you can add a payment-method fee or discount.

Use a positive value to discount NMI payments. Use a negative value to charge an extra fee.

For example:

1. `10` in the percentage field gives a 10% discount.
2. `-10` in the percentage field adds a 10% fee.
3. `5` in the fixed field gives a fixed discount.
4. `-5` in the fixed field adds a fixed fee.

***

## Configuration issues [#configuration-issues]

If NMI authentication fails during checkout, SellApp can flag the configuration issue so you know the payment method needs attention.

Check the merchant secure key, tokenization key, signing key, and enabled currencies before sending customers back through checkout.


# Paddle Payments (/docs/paddle)



SellApp makes it easy to link your [Paddle](https://paddle.com/) account and start accepting card, wallet, and other Paddle-supported payment types for your digital products. Use Paddle when you want Paddle Billing or an existing Paddle Classic account to process orders while SellApp manages the storefront and product delivery.

***

## Before you start [#before-you-start]

Paddle needs to send SellApp a webhook when a transaction is completed. &#x2A;*Without this, payments will not automatically process.**

In Paddle, create a webhook/notification destination that points to:

```txt
https://sell.app/paddle/webhook
```

For Paddle Billing, make sure the destination sends the `transaction.completed` event, then copy the webhook secret. You'll paste that secret into SellApp in the next step.

***

## Linking Paddle [#linking-paddle]

Now we can link Paddle to your SellApp storefront:

1. Navigate to [your storefront payment settings by clicking here](https://sell.app/dashboard/settings?settings=payment).
2. Click "Paddle" to open the modal. The "Paddle Billing" tab is selected by default.
3. Enter your Paddle Billing credentials:
   1. **API Key**: starts with `pdl_`
   2. **Client-side Token**: starts with `test_` or `live_`
   3. **Webhook Secret**: the secret from the Paddle webhook/notification destination you created above
4. Optionally add a discount/fee if you want to adjust the checkout total for customers who pay with Paddle.
5. Save the settings by clicking "Save" in the SellApp modal.

That's it. Paddle has been enabled for your store and you can now enable Paddle for every new product you create.

***

## Paddle Classic [#paddle-classic]

Only use the "Paddle Classic" tab if your store already uses the old Paddle Classic integration.

Classic asks for:

1. **Vendor ID**
2. **Vendor Auth Code**
3. **Public Key*&#x2A; &#x2A;(copy the full key, including `-----BEGIN PUBLIC KEY-----` and `-----END PUBLIC KEY-----`)*

New Paddle setups should use Paddle Billing instead.

***

## Optionally: Enabling Paddle for products that already exist [#optionally-enabling-paddle-for-products-that-already-exist]

If you want to enable Paddle for products that already exist, here's how to do so:

1. Navigate to [your products dashboard by clicking here](https://sell.app/dashboard/listings).
2. On the products page, toggle the checkboxes of the products you want to enable Paddle for.
3. Open the "Bulk update" dropdown and click "Payment methods".
   * A modal will pop up; check Paddle &#x2A;(& optionally other payment methods you'd like enabled)*
4. Finally, click "Update All" in the modal to update the products' payment methods.

That's all done for you: all the products you selected will now have Paddle enabled as a payment method, which customers will be able to select when making a purchase.


# Payment Methods for Digital Products (/docs/payment-methods-introduction)



Use this page to add, remove, and manage payment methods for your SellApp storefront. SellApp supports card processors, PayPal, Cash App, crypto wallets, merchant-of-record providers, Mercado Pago, Mollie, Razorpay, NMI, and custom payment methods so you can choose the checkout options that fit your digital products.

***

## Where can I add or remove a payment method? [#where-can-i-add-or-remove-a-payment-method]

You can add/remove payment methods in your SellApp storefront's payment settings.

If you don't know where that is, [here's a link to your storefront's payment settings](https://sell.app/dashboard/settings?settings=payment).

***

### How do I add or remove a payment method? [#how-do-i-add-or-remove-a-payment-method]

Each payment method has its own setup flow. Start with the method you want to enable:

<Cards>
  <Card title="Authorize.net" href="/authorize">
    Accept credit and debit card payments through Authorize.net.
  </Card>

  <Card title="CashApp" href="/cashapp">
    Configure Cash App and email forwarding so payments process automatically.
  </Card>

  <Card title="Crypto Payment Methods" href="/crypto-payment-methods-introduction">
    Link direct wallets, stablecoins, Solana, and Crypto Tokens.
  </Card>

  <Card title="Custom Payment Methods" href="/custom-payment-methods">
    Create instruction-based or redirect-based manual payment flows.
  </Card>

  <Card title="Mercado Pago" href="/mercado-pago">
    Connect Mercado Pago credentials and configure payment webhooks.
  </Card>

  <Card title="Mollie" href="/mollie">
    Accept supported one-time payments through your Mollie account.
  </Card>

  <Card title="NMI" href="/nmi">
    Accept debit and credit card payments through NMI.
  </Card>

  <Card title="Paddle" href="/paddle">
    Connect Paddle and register the SellApp webhook endpoint.
  </Card>

  <Card title="PayPal" href="/paypal">
    Link PayPal directly or enable it with your PayPal email address.
  </Card>

  <Card title="Razorpay" href="/razorpay">
    Accept supported one-time payments through your Razorpay account.
  </Card>

  <Card title="Square" href="/square">
    Add your Square access token and location ID.
  </Card>

  <Card title="Stripe" href="/stripe">
    Complete Stripe onboarding and enable it for your products.
  </Card>
</Cards>

Your payment settings may also show extra options like Paystack, Venmo, and crypto token swaps depending on what is available for your store. Those follow the same pattern: open the method, add the required account or wallet details, choose any fee or discount, and save it.

For most digital product stores, start with one card or wallet option, then add alternatives after your first sales. More payment methods can increase buyer choice, but each processor still needs correct credentials and product-level enablement.

***

## How do I enable or disable a payment method for all of my products? [#how-do-i-enable-or-disable-a-payment-method-for-all-of-my-products]

There are two ways to enable or disable a payment method for all products at once:

1. Via the [storefront payment settings](https://sell.app/dashboard/settings?settings=payment):
   1. To enable: When adding a payment method, in the payment method's popup modal, toggle "Enable X &#x2A;(where X is the payment method)* for all existing products?" on before clicking save.
   2. To disable: Remove the payment method by emptying the respective modal's input and saving. Once done, the payment method should say "Not configured" which in turn will have disabled it for all existing products that had the payment method enabled.
2. Via [your product dashboard](https://sell.app/dashboard/listings)
   1. Click the checkbox for the products on the left hand side
   2. Click "Select all" if you'd like to apply this change to all existing products in your storefront
   3. Open the "Bulk update" dropdown and click "Payment methods"
   4. Toggle the payment methods you would like to accept on &#x2A;(or keep the one you don't want to accept unchecked)*
   5. Once you click "Update All", all of the selected products will be updated to only the ones you've toggled on in step 4.

***

## How do I get my earnings? [#how-do-i-get-my-earnings]

For normal storefront orders, SellApp does not hold your money or make you wait until a specific payout date for your earned funds.

The customer does not pay our account. Instead, the money is sent from them to your linked payment processor or wallet.

That means access to the funds is handled by the payment method you enabled, not by a SellApp payout schedule.


# PayPal Payments for Digital Products (/docs/paypal)



SellApp makes it easy to link your [PayPal](https://www.paypal.com/) account and start accepting PayPal payments for your digital products. Use PayPal when customers prefer wallet checkout and you want orders tracked inside SellApp.

***

## Linking PayPal [#linking-paypal]

1. Navigate to [your storefront payment settings by clicking here](https://sell.app/dashboard/settings?settings=payment).
2. You will find a "PayPal" button. Click it, then click "Connect your PayPal account".
3. You will be redirected to PayPal and asked to give SellApp the required permissions.
4. When you are redirected back to SellApp, your PayPal account will be linked with your store.
5. If SellApp shows an action-required warning, follow it before taking live payments. This can happen if your PayPal email is not confirmed or your PayPal account is restricted from receiving payments.
6. Optionally add a discount/fee if you want to adjust the checkout total for customers who pay with PayPal.

That's it. PayPal has been enabled for your store and you can now enable PayPal for every new product you create.

***

## Optionally: Enabling PayPal for products that already exist [#optionally-enabling-paypal-for-products-that-already-exist]

If you want to enable PayPal for products that already exist, here's how to do so:

1. Navigate to [your products dashboard by clicking here](https://sell.app/dashboard/listings).
2. On the products page, toggle the checkboxes of the products you want to enable PayPal for.
3. Open the "Bulk update" dropdown and click "Payment methods".
   * A modal will pop up; check PayPal &#x2A;(& optionally other payment methods you'd like enabled)*
4. Finally, click "Update All" in the modal to update the products' payment methods.

That's all done for you: all the products you selected will now have PayPal enabled as a payment method, which customers will be able to select when making a purchase.

***

## Support: Pending PayPal payments [#support-pending-paypal-payments]

There are two types of pending PayPal payment types:

1. A pending payment where you have to accept the money on your account before the order can get processed
   1. This is due to your PayPal account not having the respective balance enabled which the customer paid with.
      * For example: if you live in the EU and only have an Euro balance enabled on your account, but then sign up to SellApp and list a product in USD, the money will be sent as USD
      * Since PayPal does not know whether you want to reject the payment, or whether you'd like to convert the USD earnings into Euro, or whether you'd like to open a separate USD balance, this payment will be set as pending until you decide
   2. The solution here is to either open a USD balance &#x2A;(it's free to open as many balances on PayPal as you'd like)*, or price your product in a currency your PayPal account has a balance opened for.
      * We strongly advise applying the solution as fast as possible, as each and every order made via SellApp will continue to remain stuck and not process until you accept/convert the payment.
2. A pending payment that has been completed on SellApp's side, but the money being held by PayPal for 1/3/7 days
   1. This is due to an internal system on PayPal's end.
      * If you're a new seller, or a seller who hasn't had activity on PayPal in a long time, they may temporarily place you into this system.
      * We at SellApp can't influence anything on this end, it's a seemingly arbitrary decision applied by PayPal
   2. The solution here is to wait it out. After a handful of successful sales with no disputes, PayPal will move you out of their system and you'll be able to accept payments instantly.


# Razorpay Payments (/docs/razorpay)



Razorpay lets you accept supported one-time payments through your own Razorpay account while SellApp manages checkout, order tracking, and delivery.

***

## Add Razorpay [#add-razorpay]

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **Razorpay**.

Enter:

1. Merchant ID.
2. Key ID.
3. Key secret.
4. Webhook secret.
5. Primary account currency.
6. Any additional supported currencies if international payments are enabled on your Razorpay account.

Then copy the SellApp webhook URL into Razorpay Dashboard > Account & Settings > Webhooks, enable all available webhook events, and save the method in SellApp.

<Note>
  The Merchant ID must match the Razorpay account used by the API keys. If it does not match, SellApp may create checkout orders, but webhooks will not complete payments automatically.
</Note>

***

## Enable Razorpay on products [#enable-razorpay-on-products]

When adding Razorpay, you can enable it for all existing products. You can also manage payment methods per variant from the product editor or with the Products dashboard bulk payment-method update.

Products using currencies outside the currencies configured for your Razorpay account will not show Razorpay at checkout.

***

## Fees or discounts [#fees-or-discounts]

Once Razorpay is active, you can add a payment-method fee or discount.

Use a positive value to discount Razorpay payments. Use a negative value to add a fee.


# Square Payments (/docs/square)



SellApp makes it easy to link your [Square](https://square.com/) account and start accepting credit or debit card, Cash App Pay, Apple Pay, Google Pay, and other Square-supported payment types for your digital products.

***

## Linking Square [#linking-square]

Here's how to link Square to your SellApp account:

1. Navigate to [your storefront payment settings by clicking here](https://sell.app/dashboard/settings?settings=payment).
2. You will find a "Square" button. Click it to open the modal which displays **two** input fields: "**Access token**" and "**Location ID**".
   1. [You can find your access token by clicking here](https://developer.squareup.com/apps). If you don't have an app yet, click "Create App" and copy the provided token.
   2. [You can find your location ID by clicking here](https://developer.squareup.com/) -> Click your app -> locations and copy the provided location ID.
3. Optionally add a discount/fee if you want to adjust the checkout total for customers who pay with Square.
4. Paste the above values in the respective inputs and save the settings by clicking "Save" in the SellApp modal.

SellApp will check the credentials and create the required Square webhook subscription automatically. If Square rejects the credentials or webhook setup, the modal will show the error before saving.

That's it. Square has been enabled for your store and you can now enable Square for every new product you create.

***

## Optionally: Enabling Square for products that already exist [#optionally-enabling-square-for-products-that-already-exist]

If you want to enable Square for products that already exist, here's how to do so:

1. Navigate to [your products dashboard by clicking here](https://sell.app/dashboard/listings).
2. On the products page, toggle the checkboxes of the products you want to enable Square for.
3. Open the "Bulk update" dropdown and click "Payment methods".
   * A modal will pop up; check Square &#x2A;(& optionally other payment methods you'd like enabled)*
4. Finally, click "Update All" in the modal to update the products' payment methods.

That's all done for you: all the products you selected will now have Square enabled as a payment method, which customers will be able to select when making a purchase.


# Stripe Payments for Digital Products (/docs/stripe)



SellApp makes it easy to link your [Stripe](https://stripe.com/) account and start accepting card, wallet, and local payment methods for your digital products. Use Stripe when you want a familiar card checkout for files, license keys, subscriptions, memberships, and other digital goods.

<Note>
  Once Stripe is enabled, customers can select a wide variety of payment methods on Stripe's checkout page. These include Apple/Google Pay, iDeal, Bancontact, Sofort, Giropay, and more.
</Note>

***

## Linking Stripe [#linking-stripe]

1. Navigate to [your storefront payment settings by clicking here](https://sell.app/dashboard/settings?settings=payment).
2. You will find a "Stripe" button. Click it to open the Stripe configuration modal.
3. Click the "**Connect Stripe**" button to be redirected to Stripe's onboarding page:
   1. If you already have a Stripe account, enter your Stripe email and log in.
   2. Otherwise, enter your email address and go through the onboarding process.
4. Once you've completed Stripe's onboarding process, you will be redirected back to your storefront's payment settings. Click "Stripe" to open the modal again,
   1. It should now say "Stripe Connected".
   2. If Stripe still needs more information before live charges can run, finish that in Stripe first.
   3. Finally, click "Enable" in the modal.
5. Optionally add a discount/fee if you want to adjust the checkout total for customers who pay with Stripe.

That's it. Stripe has been enabled for your store and you can now enable Stripe for every new product you create.

***

## Optionally: Enabling Stripe for products that already exist [#optionally-enabling-stripe-for-products-that-already-exist]

If you want to enable Stripe for products that already exist, here's how to do so:

1. Navigate to [your products dashboard by clicking here](https://sell.app/dashboard/listings).
2. On the products page, toggle the checkboxes of the products you want to enable Stripe for.
3. Open the "Bulk update" dropdown and click "Payment methods".
   * A modal will pop up; check Stripe &#x2A;(& optionally other payment methods you'd like enabled)*
4. Finally, click "Update All" in the modal to update the products' payment methods.

That's all done for you: all the products you selected will now have Stripe enabled as a payment method, which customers will be able to select when making a purchase.

***

## Support: Linking Stripe if it's already connected to another platform [#support-linking-stripe-if-its-already-connected-to-another-platform]

If your Stripe account has already been connected to another platform, and you want to link it to SellApp, you'll find it's not possible unless you disconnect the other platform's link to your account.

Here's how to do so:

* [Click here for Stripe's official guide](https://support.stripe.com/questions/disconnect-your-stripe-account-from-a-connected-third-party-platform)

1. Navigate [to the "Authorized Applications" page on your Stripe dashboard](https://dashboard.stripe.com/account/applications)
2. Click "revoke access" for the relevant platform that has already been connected to your account
3. Finally, you can now link your Stripe account to SellApp without running into any issues

Happy selling!


# Digital Product Delivery (/docs/digital-items)



Digital items are the deliverables attached to a variant. They decide what the customer receives after a successful payment, whether you sell downloadable files, license keys, serials, access codes, generated products, course access, appointment bookings, or credits.

Open a product variant, then expand **Digital Items**. For courses, open **Courses** and edit the course's pricing, access, and curriculum.

***

## Digital Delivery Types [#digital-delivery-types]

SellApp supports these delivery types:

1. **Unique Codes & Serials** for text stock delivered one-by-one, such as keys, accounts, codes, or credentials.
2. **Downloadable Files** for files customers can download after payment.
3. **Dynamic Product** for webhook-based delivery where your system generates the product after SellApp pings it.
4. **Static Value** for manual services, links, instructions, or fixed text.
5. **License key** for generated software licenses with usage and expiration controls.
6. **Course access** for structured course products with curriculum access after purchase.
7. **Booking** for appointment products with availability, slot holds, calendar sync, meeting links, and reminders.
8. **Credits** for selling prepaid credit quantities with tiered unit pricing.

You can combine delivery types when a variant needs more than one kind of fulfillment.

Course access is managed at the course product level rather than as a `deliverable.types` value. A course has one default variant for pricing and checkout, then SellApp grants access in the customer portal after a completed purchase. Course access can be lifetime or limited by duration.

***

## Unique codes and serials [#unique-codes-and-serials]

Use serials when each customer should receive unique stock. This works well for software keys, account credentials, coupon codes, gift codes, or any digital download that needs one unique value per order.

You can paste stock into the editor, upload stock, remove duplicates, and choose how SellApp should split the stock:

1. Comma
2. New line
3. Space
4. Custom delimiter

After saving, you can view, copy, and manage sold or unsold serials from the variant.

***

## Dynamic products [#dynamic-products]

Dynamic products are for custom fulfillment. SellApp sends a webhook to your endpoint, then your endpoint returns the delivered content.

Use this for generated accounts, custom keys, provisioning flows, or any product where stock should be created on demand instead of uploaded ahead of time.

Dynamic products are the best fit when your own system needs to decide what the buyer receives after checkout.

***

## License keys [#license-keys]

License keys are generated after purchase and can include:

1. A license prefix.
2. A usage limit.
3. An expiration length or unlimited duration.

After purchase, generated licenses appear in the Licenses dashboard where you can search, view customers, and manage usage.

***

## Course Access [#course-access]

Courses are product listings with a curriculum, lessons, attachments, access settings, and one default checkout variant. Customers purchase the course through checkout, then access it from the customer portal after payment.

Course access can be:

1. **Lifetime access** with no expiration.
2. **Limited access** for a fixed number of days after purchase.

SellApp snapshots the course access terms on purchase, so existing customers keep the access duration they bought even if you later change the course settings.

***

## Bookings [#bookings]

Bookings are appointment products. Customers select an available time before checkout, SellApp creates a temporary slot hold, and the appointment is confirmed after payment.

Booking products can include:

1. Slot duration and capacity.
2. Minimum notice and maximum advance booking windows.
3. Weekly availability rules.
4. Calendar sync and meeting links.
5. Customer reminders.

***

## Credits [#credits]

Credits products grant a purchased number of credits to the customer after checkout. Use them for AI token usage, in-game currency for your private gaming server, or account credit that customers can spend later.

Credits use tiered unit pricing. Each tier defines a minimum quantity, optional maximum quantity, and unit price per credit. Credits products are direct-checkout products and should not be added to normal cart flows with other products.


# Storefront Groups and Sections (/docs/groups-and-sections)



Groups and sections help customers scan your digital product catalog without digging through every product.

Use sections for broad storefront areas, then use groups when several products belong together inside or across those sections.

***

## Sections [#sections]

Open [Sections](https://sell.app/dashboard/sections) to create and sort storefront sections.

A section can have:

1. A title.
2. Hidden or visible state.
3. Products assigned to it.
4. Groups assigned to it.
5. A custom order for how items appear.

Sections are best for high-level storefront organization, such as `Accounts`, `Templates`, `Software`, `Services`, `Memberships`, or `Bundles`.

***

## Groups [#groups]

Open [Groups](https://sell.app/dashboard/groups) to create product groups.

A group can have:

1. A title.
2. An optional image.
3. An unlisted state.
4. An assigned section.
5. A manually ordered product list.

Groups are useful when products share a theme but should not be merged into one product. For example, you might group several templates, server packages, account types, license packs, or add-on services.

***

## Product placement [#product-placement]

You can assign a product directly to a section from the product editor. You can also manage placement from the Sections and Groups dashboards when you want to organize many products at once.

Keep the storefront simple. Clear sections and groups help customers find the right digital product faster, while overloaded placement can make the catalog harder to trust.


# License Key Management (/docs/license-keys)



License keys are a digital item type for software, private tools, paid communities with external access, or any product that needs a unique key after purchase. SellApp handles license key generation and delivery, then gives you a dashboard for search, usage, and expiration management.

***

## Sell a license key product [#sell-a-license-key-product]

Open a product variant, expand **Digital Items**, then select **License key**.

Configure the license data:

1. Add a license prefix if you want keys to follow your brand or product naming.
2. Set a usage limit, or make the license unlimited.
3. Set an expiration length, or make the license unlimited.
4. Save the variant.

After purchase, SellApp generates and delivers the license key to the customer. This keeps license key management connected to the order, customer email, and product variant that produced the key.

***

## Manage licenses [#manage-licenses]

Open [Licenses](https://sell.app/dashboard/licenses) to see generated license keys.

The Licenses dashboard shows:

1. The license key with prefix.
2. Status.
3. Customer email.
4. Usage count and limit.
5. Expiration.

Use search when a customer sends you a key and you need to find the matching purchase quickly.

***

## License instances [#license-instances]

License instances track where a license has been used. This is useful when your app or external platform validates license keys and registers installs, devices, projects, or workspaces.

If a customer reaches their usage limit, review the license and its instances before increasing the limit or issuing a replacement.


# Products and Variants (/docs/products-and-variants)



Products are the main listings customers browse on your store. Variants are the purchasable options inside a product, such as different plans, quantities, packages, formats, subscriptions, course access, appointments, credits, or access levels.

Open [Products](https://sell.app/dashboard/listings) to create or edit a product.

***

## Digital Product Basics [#digital-product-basics]

The product editor controls the storefront page for standard products and bookings:

1. **Title and slug** for the product name and URL.
2. **Description** for the main product copy.
3. **Visibility** for whether the product is visible or hidden.
4. **Images** for the product gallery.
5. **Section** for storefront organization.
6. **Delivery text** for post-purchase instructions.
7. **FAQ** and extra product-page settings.

You can save a product as a draft while you are still preparing the listing.

Courses use the course editor instead of the standard product editor. A course includes the same storefront basics, plus curriculum sections, lessons, attachments, promo media, and access settings.

***

## Variants [#variants]

Each product, course, or booking needs at least one variant before it is ready to sell. A variant controls the purchase details and delivery setup:

1. Title and short description.
2. Price and currency.
3. Single payment, subscription, or pay-what-you-want pricing.
4. Compare-at price for crossed-out pricing.
5. Accepted payment methods.
6. Minimum and maximum purchase quantity.
7. Volume discounts.
8. Digital items, course access, or appointment details delivered after payment.

For subscriptions, SellApp currently shows subscription pricing when Stripe or PayPal is available for the store. Use separate variants when one listing needs both one-time digital downloads and recurring access.

For courses, SellApp creates and manages one default variant for pricing and checkout. The course's access settings control whether customers receive lifetime access or limited access for a fixed number of days after purchase.

For bookings, variants control the appointment offer, including duration, timezone, capacity, and availability rules.

For credits, variants control the quantity rules and rate tiers used to price each purchased credit. Credit products are direct-checkout products and cannot be mixed into normal carts with other product types.

***

## Payment methods per variant [#payment-methods-per-variant]

Variants can use different payment methods. For example, you can offer Stripe and PayPal on a subscription variant, while another one-time variant uses crypto, Cash App, or a custom payment method.

If you use custom payment methods, select the specific custom methods that should be allowed for the variant.

***

## Bulk updates [#bulk-updates]

The Products dashboard includes bulk actions for repeated product settings such as visibility, payment methods, redirect URLs, delivery text, FAQ, additional information, and Discord invite settings.

Use bulk updates when a setting should be consistent across many products, then edit individual products for exceptions. This is useful when you add a new payment method, change post-purchase redirects, or update delivery instructions across a large digital product catalog.


# Analytics Settings (/docs/analytics-settings)



Analytics settings let you connect storefront tracking for customer behavior, conversions, and advertising optimization.

Open [Analytics settings](https://sell.app/dashboard/settings?settings=analytics).

## Google Analytics 4 [#google-analytics-4]

Enter the GA4 **Measurement ID** and optional **API Secret**. The measurement ID identifies the Google Analytics property, and the API secret enables server-side event tracking.

If a secret is already saved, enter a new value to replace it or clear the saved measurement ID and secret.

## Meta Pixel [#meta-pixel]

Enter the Meta **Pixel ID** and optional **Access Token** to track conversions and build audiences for Facebook and Instagram advertising.

If a token is already saved, enter a new token to replace it or clear the saved Pixel ID and token.

## TikTok Pixel [#tiktok-pixel]

Enter the TikTok **Pixel ID** and optional **Access Token** to track conversions and optimize TikTok advertising campaigns.

If a token is already saved, enter a new token to replace it or clear the saved Pixel ID and token.

## When to configure analytics [#when-to-configure-analytics]

Configure ecommerce analytics tracking before you run paid campaigns or launch a new product. That gives you cleaner conversion data for product pages, checkout activity, and purchase events.


# Dashboard Customization (/docs/dashboard-customization)



Dashboard customization in SellApp is controlled by the dashboard date range, selected metric, dashboard timezone, dashboard currency, and analytics cards shown for the active store.

Open [the dashboard](https://sell.app/dashboard), then use [General settings](https://sell.app/dashboard/settings?settings=general) for timezone and currency defaults.

## Date range and metrics [#date-range-and-metrics]

Use the dashboard date picker to change the reporting window. Presets include today, last 7 days, last month, last quarter, last year, this month, all time, and custom ranges.

The main dashboard cards show revenue, orders, visitors, and conversion rate. Select a metric card to switch the chart to that metric.

## Timezone and display currency [#timezone-and-display-currency]

Set **Dashboard Timezone** in General settings so order dates, charge dates, license activity, sales reports, and other dashboard timestamps match the timezone your team uses.

Set **Dashboard Currency** so revenue and reporting views use your preferred display currency.

## Live visitors and analytics cards [#live-visitors-and-analytics-cards]

The dashboard includes live visitor count, top-performing products, top-performing payment processors, visitor analytics, traffic sources, locations, devices, and recent analytics snapshots when data is available.

Use these cards to understand which products, pages, campaigns, and payment methods are driving store activity.

## Share dashboard cards [#share-dashboard-cards]

Hover or focus a supported dashboard card and choose its share action to generate a branded image for the current date range. You can share metric cards and charts, top products and processors, page and traffic-source breakdowns, locations, devices, and events.

Choose a solid, multicolor, dark, or transparent background in the preview. Then copy the image to your clipboard or download it as a PNG. The generated image uses the store's name, logo, selected metric, and reporting period.


# Delete Store Settings (/docs/delete-store-settings)



The **Other** settings tab contains destructive account or storefront actions that are only shown when your account has the required ownership access.

Open [Other settings](https://sell.app/dashboard/settings?settings=other).

## Delete a storefront [#delete-a-storefront]

If you own the current storefront, the Other tab can show the delete-store form. Use it only when you are certain the storefront should be removed.

Before deleting a store, review any products, orders, customers, custom domains, payment settings, webhooks, affiliate data, and customer support history that you may need later.

## Before using destructive actions [#before-using-destructive-actions]

Destructive settings can affect customer access and your ability to operate the store. Confirm that you are in the correct storefront, then make sure no active sales, subscriptions, community access grants, or support workflows depend on it.

If you only need to stop new purchases, consider setting the store visibility to **Private Store** in [General Store Settings](/general-store-settings) instead of deleting the storefront.


# Developer Settings (/docs/developer-settings)



Developer settings control the webhook and API tooling used to automate your SellApp store.

Open [Developer settings](https://sell.app/dashboard/settings?settings=developers).

## Webhooks [#webhooks]

Use webhooks when an external system needs to receive store events. You can create webhook endpoints, edit existing endpoints, test delivery, and review recent webhook deliveries.

Webhook delivery logs help you debug endpoint status, payloads, and recent failures without guessing whether SellApp sent an event.

For automated configuration, use the [Webhook Channels API](/api/webhook-channels) to manage destinations, event filters, test sends, and write-only signing-secret rotation.

## Webhook secret [#webhook-secret]

Generate a webhook secret when your endpoint needs to verify that incoming requests came from SellApp.

Use the secret to validate signed webhook requests before creating accounts, granting access, updating stock, or trusting an incoming order event.

For dynamic product delivery, see [Dynamic Webhook Setup](/setting-up-dynamic-webhook).

## API tokens [#api-tokens]

Use API tokens when your own system needs scoped API access to SellApp. Create tokens only for the systems that need them, and delete old tokens when they are no longer used.

Keep webhook secrets and API tokens private. Rotate them if they are exposed or copied into a place your team does not control.


# General Store Settings (/docs/general-store-settings)



General store settings control the basics of your SellApp storefront and dashboard defaults.

Open [General settings](https://sell.app/dashboard/settings?settings=general).

## Store visibility [#store-visibility]

Choose how customers can access the store:

1. **Public Store**: accessible to anyone. Products are visible and can be purchased.
2. **Hidden Store**: accessible to anyone with a link. Products can be purchased.
3. **Private Store**: inaccessible. Products are invisible and cannot be purchased.

Use Hidden when you want a private launch link, and Private when the store should stop accepting purchases.

## Store name and URL [#store-name-and-url]

Update the store name shown in the dashboard and storefront. The SellApp subdomain is shown in the Store URL field so you can confirm the active storefront address.

For a branded domain, use [custom domain setup](/linking-custom-domain).

## Dashboard timezone and currency [#dashboard-timezone-and-currency]

Choose the dashboard timezone used for dates in orders, charges, sales, licenses, and other store activity. Choose the dashboard currency used for reporting and dashboard metrics.

These settings help teams read reports in their operating timezone and preferred display currency.

## Checkout color scheme [#checkout-color-scheme]

Use **Checkout color scheme** to follow the customer's system theme or force checkout into dark or light mode.


# Payment Functionality Settings (/docs/payment-functionality-settings)



Payment functionality settings control checkout behavior around customer data, taxes, risk checks, cart behavior, email delivery, and rate limiting.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then use **Payment Functionality**.

## Checkout and customer details [#checkout-and-customer-details]

Use these settings to decide what checkout asks for and how orders are processed:

1. **Collect Billing Details** asks customers for billing details during checkout.
2. **Enable VAT** collects VAT during checkout.
3. **VAT inclusive product pricing** includes VAT in product prices instead of adding it on top.
4. **Disable Checkout Email** stops asking customers for an email address during checkout. Delivery emails cannot be sent when no customer email is available.
5. **Send Delivery Email** controls whether SellApp sends the delivery email after purchase.

Use billing details and VAT settings when your tax, invoicing, or processor workflow requires them.

## Store risk and cart controls [#store-risk-and-cart-controls]

Use **Blacklist On Dispute** to automatically blacklist a customer's email and IP if they open a dispute.

Use **Allow VPN Purchases** when customers using a VPN or proxy should still be allowed to buy. Leave stricter risk controls in place when fraud prevention is more important than allowing VPN traffic.

Use **Disable Shopping Cart** when customers should buy one product at a time instead of building a cart.

## Minimum spend and descriptor [#minimum-spend-and-descriptor]

Use **Minimum Spend** to require customers to spend at least a certain amount before checkout.

Use **Customize Billing Descriptor** to change the text customers see while checking out. The descriptor is limited to 20 characters.

## Checkout rate limits [#checkout-rate-limits]

Checkout rate limits control invoice creation attempts per store. You can set:

1. Customer attempts per hour for the same IP and email combination.
2. Optional limits per IP.
3. Optional limits per email.
4. Optional limits per checkout session fingerprint.
5. A window in seconds before attempts are allowed again.

Leave optional limits empty to disable them. Use stricter limits when you see repeated checkout abuse or bot-created invoices.

## Crypto checkout settings [#crypto-checkout-settings]

If your store has crypto wallets enabled, extra settings can appear:

1. **Underpaid Percentage** for the allowed underpayment threshold.
2. **Minimum Confirmations** for the number of block confirmations required before an order processes.

Use these settings carefully because they affect when crypto orders move forward to delivery.


# Personalization Settings (/docs/personalization-settings)



Personalization settings control customer-facing support details, invoice business information, review invitations, return links, custom email, and custom domains.

Open [Personalization settings](https://sell.app/dashboard/settings?settings=personalization).

## Support and review settings [#support-and-review-settings]

Set **Support Email** to show customers where they can contact you for help.

Set **Trustpilot Email** when you want Trustpilot to send post-purchase review invitations from SellApp delivery emails. See [Trustpilot Review Invitations](/trustpilot) for the full setup flow.

If your store has a custom email connected, use **Email Sender Name** to control the sender name shown in customer emails. Leave it blank to use SellApp.

## Business details for invoices [#business-details-for-invoices]

Business details are displayed on invoices. You can set:

1. Address.
2. City.
3. State.
4. ZIP.
5. Country.
6. Tax information.

Add the business details your customers or tax workflow need to see on receipts and invoices.

## Custom return link [#custom-return-link]

Use **Customize Return Link** to change the label and URL for the Back button on product and checkout pages.

If you leave it empty, the Back button automatically redirects to the store's home page.

## Custom email and custom domains [#custom-email-and-custom-domains]

Use **Custom Email** to send transactional emails from your own email address.

Use custom domains when your storefront should live on your own domain. See [Link a Custom Domain](/linking-custom-domain) for DNS, CNAME, TXT, and SSL setup.


# Staff Settings (/docs/staff-settings)



Staff settings control who can help manage your SellApp storefront.

Open [Staff settings](https://sell.app/dashboard/settings?settings=staff).

## Invite staff [#invite-staff]

Use the Staff tab to invite team members who need access to the storefront dashboard. Send invites only to people who should help manage products, orders, customers, payments, support, or settings.

Before inviting someone, decide what operational access they need and whether they should be trusted with sensitive areas like payment settings, developer tools, customer data, and staff management.

## Review team access [#review-team-access]

Review staff access when someone changes roles, leaves the team, or no longer needs dashboard access.

Remove users who should not be able to view store data or make changes. Keeping the staff list current helps protect order data, customer information, and payment configuration.

## Access denied states [#access-denied-states]

If a user cannot view settings, they may not have permission to update the current storefront. Ask a store owner or admin to review their team access.


# Storefront Settings (/docs/storefront-settings-introduction)



Storefront settings control how your SellApp store appears, how checkout behaves, which integrations run, and which dashboard defaults your team uses.

Open [Settings](https://sell.app/dashboard/settings) from the SellApp dashboard.

## Settings tabs [#settings-tabs]

The settings page is organized into tabs:

1. **General** for visibility, store name, dashboard timezone, dashboard currency, and checkout color scheme.
2. **Payment** for payment methods, billing details, VAT, checkout rules, minimum spend, rate limits, and crypto checkout controls.
3. **Notifications** for Discord and email notification channels.
4. **Analytics** for Google Analytics 4, Meta Pixel, and TikTok Pixel tracking.
5. **Personalization** for support email, Trustpilot, business invoice details, return links, custom email, and custom domains.
6. **Affiliates**, **Community**, and **Marketing** for growth and access settings.
7. **Staff** for team member access.
8. **Developers** for webhooks, webhook secrets, recent deliveries, and API tokens.
9. **Other** for destructive store actions shown to store owners.

## Where to start [#where-to-start]

Start with General settings and Payment settings before publishing a store. Then configure Analytics, Personalization, Notifications, and Developer settings based on how your store handles tracking, customer support, and automation.

Use the dedicated docs in this section for settings that affect checkout behavior, reporting, customer emails, team access, developer automation, and operational risk.


# Storefront Builder (/docs/storefront-builder-introduction)



The SellApp storefront builder gives you full control over your storefront's design, product layout, page structure, and SEO settings.

We created the storefront builder with ease and simplicity in mind. You can use the builder without touching any code, and design your digital product store with a drag-and-drop interface.

To get started with the builder, click the "Store Builder" button in the sidebar of the SellApp dashboard.

If you see an "Authorization Request" screen, click "Authorize" to let the builder access the store you are currently managing. Only store owners and admins can authorize the builder.

***

## Storefront Builder Basics [#storefront-builder-basics]

<iframe className="w-full h-[315px]" src="https://www.youtube.com/embed/cM41yVBRbMQ?si=7gOB8v0NUGcL84xh" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" />

There are a number of aspects that are worth explaining to help you become familiar with the builder and its functionality:

Summed up briefly: The builder is a collection of **pages**. Pages house **sections** containing **blocks**. A more elaborate explanation:

* A storefront is a collection of pages
  * Each page is comprised of three aspects:
    * **Navigation bar**: The navigation bar is the same across all pages
      * The navigation bar does not consist of sections and blocks, it only has unique configuration options, found in the sidebar on the left side of the editor
    * **Body**: The body is unique for each page
      * The body is comprised of **sections**
        * Sections consist of **blocks**
          * Blocks can be **text**, a **button**, an **image**, and so on
          * You can **drag & drop blocks** within a section
          * Blocks each have their **unique configuration options**, found in the **sidebar on the left side** of the editor
    * **Footer**: The footer is the same across all pages
      * Unlike the navigation bar, the footer also consists of sections and blocks.
  * Each page has its own settings (SEO). To configure the page, **click the tab of the page** and its settings will appear in the sidebar on the left side of the editor
* There are also site-wide options and settings. To configure site-wide options and settings, **click the settings button**, found to the right side of the browser address bar

Of note is that a store design is not automatically mobile-optimized. To switch between a design's desktop & mobile design, you will want to click their respective option found above the sidebar, next to the "Preview" button.

***

## Site-wide settings [#site-wide-settings]

To configure site-wide options and settings, **click the settings button**, found to the right side of the browser address bar.

Generally speaking, the site-wide settings are your starting point. Here, you can configure the following:

* **Configure site-wide SEO settings**
* **Text configuration**: Font family, toggle RTL (right-to-left) language, set text colour (can be overridden per section and/or text)
* **Colour palette**: Create an assortment of colours. From normal ones, to gradients
* **Button**: Create/edit variations, each with their own effects, colours, and so on
* **Design system**: Set a global background colour or image, and border radius

Once you've configured these, you're ready to start creating pages, sections, and configure blocks

***

## Navigation bar [#navigation-bar]

**Unlike the body and footer, the navigation bar does not consist of sections and blocks.** It only has unique configuration options, found in the sidebar on the left side of the editor

To open the navigation bar's settings, click "Edit navigation".

For some use-cases, you might find having a navigation bar to be detrimental to your store's design and conversion rate. Given this, the first option is whether or not you'd like to have the navigation bar enabled.

Secondly is the brand name. You may leave it empty or enter your store's brand name, which will be visible at the left side of the navigation bar

Finally there are the navigation bar items. A navigation bar is comprised of multiple items, but each item is one of two types: a link, or a spacer.

* **A link consists of a label** (text) and a link to which the label points. There are three types of links
  * **An internal URL**: Useful to point to another page within your storefront
  * **An external URL**: Useful to point to an external site, such as google.com, or a specific ID of an element within the page, such as #promotion.
  * **A specific product**

Worth noting is that each link can be rendered as a button, if needed.

* A spacer is commonly used to style the assortment of links in your navigation bar.
  * With 1 spacer, you can push links to the rightmost side of your navigation bar.
  * With two spacers, you can have the links centered within the navigation bar.

***

## Creating a new page [#creating-a-new-page]

To create a new page, click the &#x2A;*+** icon next to the tab in the editor's browser

***

## Sections & Blocks [#sections--blocks]

Both the body and footer are comprised of sections, which house blocks themselves.

* Sections can be anything you want; a **hero**, a **featured product list**, and so on.
  * Note that you are not required to utilize multiple sections and can house everything within one big section, though we advise to utilize multiple sections for the sake of simplicity.
* Blocks are elements found within a section.
  * These can be **static content**, such as a heading, a rectangle, and so on
  * These can also be **dynamic content**, such as a product list, or feedback
    * Dynamic content is **fetched directly from your SellApp storefront**
    * The builder can pull in storefront data such as products, groups, sections, feedback, and published stories/highlights
  * **Each block has their own set of configurable options** which will appear in the sidebar on the left when you click on the respective block

***

## Publishing a store design [#publishing-a-store-design]

<Warn>
  A store design is not automatically mobile-optimized. To review your store's mobile design before publishing, you will want to click the mobile button icon found above the sidebar, next to the "Preview" button.
</Warn>

Once you've created a store design you're satisfied with on both the desktop and mobile version, you are ready to publish the design to the world.

To do so, &#x2A;*simply click the "Publish" button at the top right.** Until you publish, your changes stay in the builder draft. Once it has been published, a modal will appear to let you know this has been done.

***

**And that's it, you've created a store design of your own and published it for the world to see and interact with.**


# API Reference (/docs/api)



Build your own checkout, manage your catalog, or connect SellApp to the tools
your business already uses. Start with a read-only request below, then follow
one purchase from product setup to webhook delivery.

The base URL is `https://sell.app/api`. Requests
operate on the real data of the store selected by `X-STORE`; there is no
separate API sandbox.

Use API keys for your own integrations. To connect the official SellApp CLI,
run `sellapp login` and follow [CLI authorization](/api/oauth-authorization).
OAuth access is supported only for the official CLI.

## Make a harmless request [#make-a-harmless-request]

1. Create a secret key in your [store developer settings](https://sell.app/dashboard/settings?settings=developers).
2. Copy the store slug from its storefront URL. For `launch-lab.sell.app`, the slug is `launch-lab`.
3. Give your key the `listing` ability (permission to access the catalog), replace the values below, and run this in your terminal:

```bash title="List the first product"
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/products?limit=1" \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Accept: application/json'
```

A successful response is `200 OK` and includes an `X-Request-ID` response header
for debugging. The `data` array contains your products, one page at a time.
Your product names and IDs will differ from this example:

```json title="Response — abbreviated"
{
  "data": [
    {
      "id": 120,
      "title": "Design course",
      "slug": "design-course",
      "visibility": "HIDDEN"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/products?page=1",
    "last": "https://sell.app/api/v2/products?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "per_page": 1,
    "total": 1
  }
}
```

No products yet? An empty `data` array still means the request worked. A `401` means the key is
missing or invalid. A `403` means the key or account lacks access. A `404`
after changing `X-STORE` usually means that slug is wrong or unavailable to the
authenticated account.

## Build the first sale [#build-the-first-sale]

The usual integration path is:

```text
Register and test webhook → create product → configure variant → create order → checkout → process events
```

Follow the [first-request guide](/api/quickstart), then use the workflow and
operating guides below before letting your integration change live data.

<Cards>
  <Card title="Make your first request" href="/api/quickstart">
    Read one product using cURL, an official SDK, or the CLI.
  </Card>

  <Card title="Testing safely" href="/api/testing">
    Keep test data separate and check how your app handles failures.
  </Card>

  <Card title="Sell a product" href="/api/sell-a-product">
    Create a hidden product and its first purchasable variant.
  </Card>

  <Card title="Create a checkout" href="/api/create-a-checkout">
    Create an order and retrieve its customer checkout URL.
  </Card>

  <Card title="Errors and retries" href="/api/errors">
    Understand what went wrong and when it is safe to try again.
  </Card>

  <Card title="Webhooks" href="/api/webhooks">
    Verify incoming events and handle repeated deliveries safely.
  </Card>
</Cards>

## For agents and automation [#for-agents-and-automation]

Start with [authentication](/api/authentication) and [one read](/api/quickstart).
Choose an [SDK resource reference](/api/sdks), or inspect one CLI operation with
`sellapp commands products create --json`. Use the returned schema and examples
before constructing inputs. [Errors and retries](/api/errors) explains recovery.
Each endpoint's Markdown export includes its inputs, permissions, and examples;
you do not need to load the entire OpenAPI document for one operation.


# Bitcoin Payments (/docs/bitcoin-payments)



Use Bitcoin payments when customers should pay for digital products with BTC and funds should route through the Bitcoin wallet setup connected to your SellApp store.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **Bitcoin** under **Cryptocurrencies**.

## Connect Bitcoin [#connect-bitcoin]

Enter your Bitcoin XPUB, then save the method. If you use Exodus, copy the second Bitcoin XPUB in the export list, which starts with `zpub`. SellApp recommends Electrum or Exodus for XPUB-based Bitcoin setup.

Do not use an XPUB from an exchange or Ledger. Those setups can cause funds to appear in addresses you cannot access from the wallet you expected.

## Enable Bitcoin on products [#enable-bitcoin-on-products]

When saving Bitcoin, you can enable it for all existing products. You can also control Bitcoin per variant from the product editor or bulk update payment methods from the Products dashboard.

Use Bitcoin for products where crypto checkout is expected, then keep card or wallet methods enabled when you also want a lower-friction checkout option for other buyers.


# BNB Payments (/docs/bnb-payments)



Use BNB payments when customers should pay with BNB and funds should route to your configured BNB wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **BNB** under **Cryptocurrencies**.

## Connect BNB [#connect-bnb]

Enter your BNB wallet address. If the modal shows **Minimum Withdrawal**, optionally set the minimum BNB amount before funds are forwarded to your wallet. Leave it empty if you want forwarding to happen as soon as possible.

## Enable BNB on products [#enable-bnb-on-products]

When saving BNB, you can enable it for all existing products. You can also control BNB per variant from the product editor or with the Products dashboard bulk payment-method update.

If customers prefer stablecoins on BNB Smart Chain, configure USDT BEP20 or USDC BEP20 instead.


# Crypto Payment Methods (/docs/crypto-payment-methods-introduction)



SellApp lets you accept crypto payments for digital products through direct wallet payment methods and a broader Crypto Tokens checkout. Direct wallets send payments to the wallet details you configure, while Crypto Tokens lets buyers pay with a wider token set and settle funds into an eligible wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then scroll to **Cryptocurrencies**.

## Direct crypto wallets [#direct-crypto-wallets]

Direct wallet methods are best when you know which coin or token your buyers want to use. SellApp supports:

1. Bitcoin.
2. Litecoin.
3. Ethereum.
4. BNB.
5. Tron.
6. Polygon.
7. Solana.
8. Monero.
9. ERC20 tokens: USDT, USDC, UNI, SHIB, and DAI.
10. BEP20 tokens: USDT and USDC.
11. Solana tokens: USDT and USDC.

Some wallets support a minimum withdrawal amount before funds are forwarded. If the option appears, leave it empty to forward funds as soon as possible.

## Crypto Tokens [#crypto-tokens]

Crypto Tokens lets customers pay with a larger token selection through a widget, then settle the payment into a wallet you choose. Before enabling Crypto Tokens, you need at least one eligible destination wallet enabled in SellApp.

Eligible destination wallets include supported Bitcoin, Ethereum, BNB Smart Chain, Polygon, Solana, and configured USDT or USDC wallets.

## Product-level enablement [#product-level-enablement]

When you add a crypto payment method, you can enable it for all existing products. You can also manage crypto methods per product variant from the product editor or with the Products dashboard bulk payment-method update.

Use product-level controls when only specific products should accept crypto payments, such as digital downloads, license keys, or manual-review products.


# Crypto Tokens (/docs/crypto-tokens)



Crypto Tokens lets buyers pay with a broad token selection through a checkout widget while funds settle to a wallet you choose. Use it when customers ask for more token flexibility than a single direct crypto payment method provides.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **Crypto Tokens** under **Cryptocurrencies**.

## Add an eligible settlement wallet [#add-an-eligible-settlement-wallet]

Before enabling Crypto Tokens, enable at least one supported wallet in SellApp. Eligible destinations include supported Bitcoin, Ethereum, BNB Smart Chain, Polygon, Solana, and configured USDT or USDC wallets.

If no eligible wallet is enabled, the Crypto Tokens modal will show a warning and ask you to add a supported crypto wallet first.

## Choose the settlement wallet [#choose-the-settlement-wallet]

In the Crypto Tokens modal, choose the wallet that should receive settled funds. SellApp only lists wallets that are already enabled and eligible for the store.

If the previously selected destination is no longer eligible, the modal will warn you so you can choose another wallet or disable Crypto Tokens.

## Enable Crypto Tokens on products [#enable-crypto-tokens-on-products]

When saving Crypto Tokens, you can enable it for all existing products. You can also manage it per product variant from the product editor or with the Products dashboard bulk payment-method update.

Use Crypto Tokens when you want a flexible crypto payment method without maintaining a separate direct wallet setup for every token customers might hold.


# DAI ERC20 Payments (/docs/dai-erc20-payments)



Use DAI ERC20 payments when customers should pay with DAI on Ethereum and funds should route to your configured DAI ERC20 wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **DAI ERC20** under **Cryptocurrencies**.

## Connect DAI ERC20 [#connect-dai-erc20]

Enter the wallet address that should receive DAI on Ethereum. If the modal shows **Minimum Withdrawal**, optionally set the minimum amount before funds are forwarded. Leave it empty if you want forwarding to happen as soon as possible.

## Enable DAI ERC20 on products [#enable-dai-erc20-on-products]

When saving DAI ERC20, you can enable it for all existing products. You can also control it per variant from the product editor or with the Products dashboard bulk payment-method update.

DAI can be useful when customers want a stablecoin checkout option on Ethereum.


# Ethereum Payments (/docs/ethereum-payments)



Use Ethereum payments when customers should pay with ETH and funds should route to your configured Ethereum wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **Ethereum** under **Cryptocurrencies**.

## Connect Ethereum [#connect-ethereum]

Enter your Ethereum wallet address. If the modal shows **Minimum Withdrawal**, optionally set the minimum ETH amount before funds are forwarded to your wallet. Leave it empty if you want forwarding to happen as soon as possible.

After saving, SellApp creates or updates the crypto wallet setup for your store.

## Enable Ethereum on products [#enable-ethereum-on-products]

When saving Ethereum, you can enable it for all existing products. You can also manage Ethereum per variant from the product editor or with the Products dashboard bulk payment-method update.

If buyers need ERC20 stablecoins or tokens instead of ETH, enable the relevant ERC20 payment method or use Crypto Tokens.


# Litecoin Payments (/docs/litecoin-payments)



Use Litecoin payments when customers should pay with LTC and funds should route through the Litecoin wallet setup connected to your SellApp store.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **Litecoin** under **Cryptocurrencies**.

## Connect Litecoin [#connect-litecoin]

Enter your Litecoin XPUB, then save the method. SellApp recommends Electrum or Exodus for XPUB-based Litecoin setup.

Do not use an XPUB from an exchange or Ledger. Those setups can cause funds to appear in addresses you cannot access from the wallet you expected.

## Enable Litecoin on products [#enable-litecoin-on-products]

When saving Litecoin, you can enable it for all existing products. You can also control Litecoin per variant from the product editor or bulk update payment methods from the Products dashboard.

Litecoin can be a useful alternative when buyers want direct crypto payment but prefer a different network from Bitcoin.


# Monero Payments (/docs/monero-payments)



Use Monero payments when customers should pay with XMR and funds should route through the Monero wallet details connected to your SellApp store.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **Monero** under **Cryptocurrencies**.

## Connect Monero [#connect-monero]

Enter the Monero address and the wallet's **Private View Key**. SellApp needs both values to watch for payments and process orders correctly.

After saving, SellApp validates the Monero setup and makes XMR available as a payment method for products that allow it.

## Enable Monero on products [#enable-monero-on-products]

When saving Monero, you can enable it for all existing products. You can also control Monero per variant from the product editor or with the Products dashboard bulk payment-method update.

Use clear checkout and delivery instructions when a product accepts crypto payment methods that customers may need more time to complete.


# Polygon Payments (/docs/polygon-payments)



Use Polygon payments when customers should pay with MATIC and funds should route to your configured Polygon wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **Polygon** under **Cryptocurrencies**.

## Connect Polygon [#connect-polygon]

Enter your MATIC wallet address, then save the method. SellApp will validate the wallet setup and make Polygon available as a checkout option for products that allow it.

## Enable Polygon on products [#enable-polygon-on-products]

When saving Polygon, you can enable it for all existing products. You can also control Polygon per variant from the product editor or with the Products dashboard bulk payment-method update.

Polygon can also be used as an eligible destination wallet for Crypto Tokens when it is enabled for your store.


# SHIB ERC20 Payments (/docs/shib-erc20-payments)



Use SHIB ERC20 payments when customers should pay with SHIB on Ethereum and funds should route to your configured SHIB ERC20 wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **SHIB ERC20** under **Cryptocurrencies**.

## Connect SHIB ERC20 [#connect-shib-erc20]

Enter the wallet address that should receive SHIB on Ethereum. If the modal shows **Minimum Withdrawal**, optionally set the minimum amount before funds are forwarded. Leave it empty if you want forwarding to happen as soon as possible.

## Enable SHIB ERC20 on products [#enable-shib-erc20-on-products]

When saving SHIB ERC20, you can enable it for all existing products. You can also control it per variant from the product editor or with the Products dashboard bulk payment-method update.

Keep product checkout options intentional. If SHIB is only relevant to a few products, enable it only on those variants.


# Solana Payments (/docs/solana-payments)



Use Solana payments when customers should pay with SOL and funds should route to your configured Solana wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **Solana** under **Cryptocurrencies**.

## Connect Solana [#connect-solana]

Enter your Solana wallet address. If the modal shows **Minimum Withdrawal**, optionally set the minimum SOL amount before funds are forwarded to your wallet. Leave it empty if you want forwarding to happen as soon as possible.

## Enable Solana on products [#enable-solana-on-products]

When saving Solana, you can enable it for all existing products. You can also control Solana per variant from the product editor or with the Products dashboard bulk payment-method update.

If customers prefer stablecoins on Solana, configure USDT Solana or USDC Solana. Solana can also be an eligible settlement wallet for Crypto Tokens.


# Tron Payments (/docs/tron-payments)



Use Tron payments when customers should pay with TRX and funds should route to your configured Tron wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **Tron** under **Cryptocurrencies**.

## Connect Tron [#connect-tron]

Enter your Tron wallet address. If the modal shows **Minimum Withdrawal**, optionally set the minimum TRX amount before funds are forwarded to your wallet. Leave it empty if you want forwarding to happen as soon as possible.

## Enable Tron on products [#enable-tron-on-products]

When saving Tron, you can enable it for all existing products. You can also control Tron per variant from the product editor or with the Products dashboard bulk payment-method update.

Keep the product's delivery and payment instructions clear so customers know which crypto option they selected at checkout.


# UNI ERC20 Payments (/docs/uni-erc20-payments)



Use UNI ERC20 payments when customers should pay with UNI on Ethereum and funds should route to your configured UNI ERC20 wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **UNI ERC20** under **Cryptocurrencies**.

## Connect UNI ERC20 [#connect-uni-erc20]

Enter the wallet address that should receive UNI on Ethereum. If the modal shows **Minimum Withdrawal**, optionally set the minimum amount before funds are forwarded. Leave it empty if you want forwarding to happen as soon as possible.

## Enable UNI ERC20 on products [#enable-uni-erc20-on-products]

When saving UNI ERC20, you can enable it for all existing products. You can also control it per variant from the product editor or with the Products dashboard bulk payment-method update.

If you want to support a broader token list without creating a dedicated direct wallet for every buyer preference, configure Crypto Tokens as well.


# USDC BEP20 Payments (/docs/usdc-bep20-payments)



Use USDC BEP20 payments when customers should pay with USDC on BNB Smart Chain and funds should route to your configured USDC BEP20 wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **USDC BEP20** under **Cryptocurrencies**.

## Connect USDC BEP20 [#connect-usdc-bep20]

Enter the wallet address that should receive USDC on BNB Smart Chain. If the modal shows **Minimum Withdrawal**, optionally set the minimum amount before funds are forwarded. Leave it empty if you want forwarding to happen as soon as possible.

## Enable USDC BEP20 on products [#enable-usdc-bep20-on-products]

When saving USDC BEP20, you can enable it for all existing products. You can also control it per variant from the product editor or with the Products dashboard bulk payment-method update.

Make sure customers know this is the BEP20 version of USDC, not USDC on Ethereum, Solana, or another network.


# USDC ERC20 Payments (/docs/usdc-erc20-payments)



Use USDC ERC20 payments when customers should pay with USDC on Ethereum and funds should route to your configured USDC ERC20 wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **USDC ERC20** under **Cryptocurrencies**.

## Connect USDC ERC20 [#connect-usdc-erc20]

Enter the wallet address that should receive USDC on Ethereum. If the modal shows **Minimum Withdrawal**, optionally set the minimum amount before funds are forwarded. Leave it empty if you want forwarding to happen as soon as possible.

## Enable USDC ERC20 on products [#enable-usdc-erc20-on-products]

When saving USDC ERC20, you can enable it for all existing products. You can also control it per variant from the product editor or with the Products dashboard bulk payment-method update.

Make sure customers know this is the Ethereum ERC20 version of USDC, not USDC on another network.


# USDC Solana Payments (/docs/usdc-solana-payments)



Use USDC Solana payments when customers should pay with USDC on Solana and funds should route to your configured USDC Solana wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **USDC Solana** under **Cryptocurrencies**.

## Connect USDC Solana [#connect-usdc-solana]

Enter the wallet address that should receive USDC on Solana. If the modal shows **Minimum Withdrawal**, optionally set the minimum amount before funds are forwarded. Leave it empty if you want forwarding to happen as soon as possible.

## Enable USDC Solana on products [#enable-usdc-solana-on-products]

When saving USDC Solana, you can enable it for all existing products. You can also control it per variant from the product editor or with the Products dashboard bulk payment-method update.

Make sure customers know this is the Solana version of USDC, not USDC on Ethereum, BNB Smart Chain, or another network.


# USDT BEP20 Payments (/docs/usdt-bep20-payments)



Use USDT BEP20 payments when customers should pay with Tether on BNB Smart Chain and funds should route to your configured USDT BEP20 wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **USDT BEP20** under **Cryptocurrencies**.

## Connect USDT BEP20 [#connect-usdt-bep20]

Enter the wallet address that should receive USDT on BNB Smart Chain. If the modal shows **Minimum Withdrawal**, optionally set the minimum amount before funds are forwarded. Leave it empty if you want forwarding to happen as soon as possible.

## Enable USDT BEP20 on products [#enable-usdt-bep20-on-products]

When saving USDT BEP20, you can enable it for all existing products. You can also control it per variant from the product editor or with the Products dashboard bulk payment-method update.

Make sure customers know this is the BEP20 version of USDT, not USDT on Ethereum, Solana, or another network.


# USDT ERC20 Payments (/docs/usdt-erc20-payments)



Use USDT ERC20 payments when customers should pay with Tether on Ethereum and funds should route to your configured USDT ERC20 wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **USDT ERC20** under **Cryptocurrencies**.

## Connect USDT ERC20 [#connect-usdt-erc20]

Enter the wallet address that should receive USDT on Ethereum. If the modal shows **Minimum Withdrawal**, optionally set the minimum amount before funds are forwarded. Leave it empty if you want forwarding to happen as soon as possible.

## Enable USDT ERC20 on products [#enable-usdt-erc20-on-products]

When saving USDT ERC20, you can enable it for all existing products. You can also control it per variant from the product editor or with the Products dashboard bulk payment-method update.

Make sure customers know this is the Ethereum ERC20 version of USDT, not USDT on another network.


# USDT Solana Payments (/docs/usdt-solana-payments)



Use USDT Solana payments when customers should pay with Tether on Solana and funds should route to your configured USDT Solana wallet.

Open [Payment settings](https://sell.app/dashboard/settings?settings=payment), then open **USDT Solana** under **Cryptocurrencies**.

## Connect USDT Solana [#connect-usdt-solana]

Enter the wallet address that should receive USDT on Solana. If the modal shows **Minimum Withdrawal**, optionally set the minimum amount before funds are forwarded. Leave it empty if you want forwarding to happen as soon as possible.

## Enable USDT Solana on products [#enable-usdt-solana-on-products]

When saving USDT Solana, you can enable it for all existing products. You can also control it per variant from the product editor or with the Products dashboard bulk payment-method update.

Make sure customers know this is the Solana version of USDT, not USDT on Ethereum, BNB Smart Chain, or another network.


# API changelog (/docs/api/api-changelog)



Filter the machine-readable feed at [`/api-changelog.json`](/api-changelog.json)
by `category`, `api_versions`, or `breaking`.

## 2026-08-30 [#2026-08-30]

* Added `X-Request-ID` to every API response and structured error metadata.
* Documented the 60-request-per-minute limit and rate-limit headers.
* Added stable `id` and `created_at` metadata to seller webhook event payloads.
* Marked retired v1 listing and invoice operations as deprecated with v2 replacements.
* Clarified OpenAPI document releases and URL compatibility versions.
* Added quickstart, testing, retry, idempotency, rate-limit, versioning, and workflow guides.


# Authentication (/docs/api/authentication)



Use an API key for your own integrations. The official SellApp CLI uses OAuth
on supported v2 endpoints and manages its credentials for you. Two headers
identify the caller and select a store:

* `Authorization: Bearer …` contains your API key or OAuth access token.
* `X-STORE` selects the store by its slug, such as `launch-lab`.

The CLI sends its OAuth access token and `X-STORE` on store business requests.
Your current store permissions, approved scopes, and selected stores constrain
its access. Follow [CLI authorization](/api/oauth-authorization) to connect it
with `sellapp login`. OAuth is not available for custom applications.

Profile, accessible-store, and installation-management operations use OAuth
without `X-STORE`; the effective-permissions operation requires it.
Customer Portal endpoints use a 15-minute customer-session bearer token and
return only that customer's redacted resources. Do not swap these token types:
each endpoint reference names the credential it expects.

The base URL is `https://sell.app/api`. Requests operate on the real data of
the selected store; SellApp does not provide a separate API sandbox.

## Authentication with a secret API key [#authentication-with-a-secret-api-key]

Send your key in the `Authorization` header, with the word `Bearer` and a space
before it. Keep this on your server: never put a secret key in browser code,
mobile app bundles, public repositories, or screenshots.

Set `SELLAPP_API_BASE_URL`, `SELLAPP_API_KEY`, and `SELLAPP_STORE` as shown
in [the quickstart](/api/quickstart#1-set-your-credentials).

```bash title="Example request with bearer token"
curl --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/invoices" \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json'
```

## Creating and managing a secret API key [#creating-and-managing-a-secret-api-key]

If you do not already have a secret API key, you can generate one in your [store
developers settings](https://sell.app/dashboard/settings?settings=developers).
Always keep your API key safe and rotate it if you suspect it has been
compromised.

API keys belong to an account, not a storefront. Each key has **abilities**:
permissions such as `listing` for catalog access or `invoice` for purchases.
Enable only the abilities your integration needs.

Both the key and the account must have permission for an operation. Store owners
still need the relevant key abilities; staff accounts also need the matching
store permissions. Provider limits and resource-state rules still apply.

Affiliate payout endpoints manage records of payments arranged by the merchant.
Their permissions do not authorize SellApp to transfer funds. Customer wallet
and credit endpoints separately manage customer prepaid credit.

If your account is part of a storefront as support staff, you can only access
resources that your account has been given permission to manage. For example, a
support staff account limited to tickets cannot modify products or create groups
through the API.

Every response includes an `X-Request-ID`. Log it for support and debugging,
but never log the bearer key.

## Multiple stores [#multiple-stores]

Send `X-STORE` on every store business request to select the intended store.
OAuth requires it. Ordinary API-key routes can fall back to the account's current
or first available store when it is omitted; routes that explicitly require the
header reject its omission. Always send it so a change in the account's current
store cannot redirect your integration's work.

The value is the storefront **slug**, not its numeric ID. A wrong or
unknown slug returns `404`; a valid store that the account cannot manage returns
`403`.

If you want to access `launch-lab.sell.app`, you would pass the slug `launch-lab` via the
`X-STORE` header:

```bash title="Example request accessing launch-lab.sell.app invoices"
curl --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/invoices" \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json'
```

## Using an SDK [#using-an-sdk]

An SDK can handle request setup for you, but check that it sends both the bearer
key and `X-STORE`. A library does not change the permissions your key needs.

For currently known packages and integrations, see [SDKs &
Extensions](/api/sdks).


# SellApp CLI (/docs/api/cli)



Use the official `sellapp` CLI to work with your stores from the terminal.

To build from the CLI source, install Go and run these commands from the source
directory:

```bash
go build -o sellapp ./cmd/sellapp
./sellapp --help
```

Move the executable to a directory on your `PATH`, or use `./sellapp` in place of
`sellapp` below. On Windows, build with `go build -o sellapp.exe ./cmd/sellapp`.

## First request [#first-request]

With the binary on your path, connect the official CLI and select a store:

```bash
sellapp login
sellapp stores list
sellapp stores use launch-lab
sellapp products list --limit 1 --output json
```

Approve the browser consent using your existing store permissions. See
[CLI authorization](/api/oauth-authorization) for narrower scopes, troubleshooting,
and personal disconnect. A server-side API key with the `listing` ability remains
available for automation through `SELLAPP_API_KEY` and `SELLAPP_STORE`.

The CLI prints the products as a JSON array. `[]` with exit code `0` means
your store has no products and the request worked. The HTTP API wraps that
array in `data`; the CLI list output unwraps it.
See [first-request troubleshooting](/api/quickstart) if authentication fails.

## Find the next command [#find-the-next-command]

```bash
sellapp search products
sellapp products create --help
sellapp commands products create --json
sellapp docs products create
```

The command schema describes its inputs and effects. Use the resource ID as a
positional argument and parent IDs as named flags:

```bash
sellapp products get 120
sellapp product-variants get 4321 --product 120
```

## Edit your catalog [#edit-your-catalog]

These requests create real records. A complete ordinary catalog edit runs
directly; the terminal prompts for missing required inputs. Scripts must supply
them explicitly.

```bash
sellapp products create \
  --title "Design kit" \
  --description "Templates for your next project." \
  --visibility HIDDEN
```

Use `--body @file.json` or `--body -` for complex JSON. Use `--set FIELD=JSON`
for explicit nulls or nested values. Supplying the same field twice is an error.
Do not combine stdin for a body with stdin for an upload.

Consequential actions, including checkout creation and deletion, require
confirmation. Supply `--yes` in automation only when you intend the effect.
Use `--dry-run` to build a redacted request without contacting the API.

## Automation [#automation]

Redirected output defaults to JSON. Explicit `--output` always wins. Response
data goes to stdout; diagnostics go to stderr. One page is the default;
`--all` enables pagination, with `--max-items` and `--max-pages` available to bound it.

```bash
sellapp products list --all --max-items 100 --output json > products.json
```

Configure an API key or authorize a CLI profile before running
automation. Noninteractive commands do not start login implicitly. See
[OAuth authorization](/api/oauth-authorization) for credential isolation and
store access.


# Create a checkout (/docs/api/create-a-checkout)



This continues the Design kit example: Maya buys the configured
`STRIPE` one-time variant for $19.99. First create the purchase
through the orders API, then get the checkout URL to send to Maya.

## 1. Prepare the variant and receiver [#1-prepare-the-variant-and-receiver]

You need Bash, cURL, `jq`, an `invoice`-enabled API token with store permission,
and a purchasable variant from the same store. Replace the key, slug, and
variant ID with your own values.

Before creating the order, configure and test a signed webhook receiver for
`order.created`, `order.paid`, and `order.completed`.
The [advanced walkthrough](/api/subscription-checkout#2-register-and-test-the-webhook-first)
includes the registration and test requests. The receiver must save the full
payload and recoverable pending work before returning a success response.

These are real store records. Opening and completing checkout can charge the
customer.

```bash title="Run once in the same Bash session"
set -euo pipefail
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

api() {
  local method="$1" path="$2"
  shift 2
  curl --silent --show-error --fail-with-body \
    --request "$method" --url "${SELLAPP_API_BASE_URL}${path}" \
    --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
    --header "X-STORE: ${SELLAPP_STORE}" \
    --header 'Accept: application/json' \
    --dump-header /dev/stderr "$@"
}

api GET '/v2/products?limit=1' | jq '.data'
```

```bash title="Use the variant returned by product setup"
export SELLAPP_VARIANT_ID='4321'
```

## 2. Create Maya's order and checkout session [#2-create-mayas-order-and-checkout-session]

```bash title="Create the purchase and obtain its actual checkout URL"
order_json=$(api POST /v2/orders \
  --header 'Idempotency-Key: launch-lab-maya-order-001' \
  --header 'Content-Type: application/json' \
  --data "$(jq -nc --arg variant "$SELLAPP_VARIANT_ID" '{
    customer_email:"maya@example.com",
    payment_method:"STRIPE",
    product_variants:{($variant):{quantity:1}}
  }')")
SELLAPP_ORDER_ID=$(jq -er '.data.id' <<< "$order_json")

checkout_json=$(api POST "/v2/orders/${SELLAPP_ORDER_ID}/checkout" \
  --header 'Idempotency-Key: launch-lab-maya-checkout-001')
SELLAPP_CHECKOUT_URL=$(jq -er '.data.payment.checkout_url' <<< "$checkout_json")
printf '%s\n' "$SELLAPP_CHECKOUT_URL"
```

Order creation returns `201`; checkout returns `201` for a new payment session
or `200` when reusing an existing session. Both return an order
under `data` and include `data.payment.checkout_url` when a URL is available.

```json title="Order response — abbreviated"
{"data":{"id":9001,"status":"PENDING","customer":{"email":"maya@example.com"},"payment":{"checkout_url":"https://checkout.stripe.com/c/pay/cs_example"},"totals":{"currency":"USD","total_cents":1999}}}
```

```json title="Checkout response — abbreviated, illustrative URL"
{"data":{"id":9001,"status":"PENDING","payment":{"checkout_url":"https://checkout.stripe.com/c/pay/cs_example"}}}
```

Open the URL printed by your request, not the illustrative URL above. Completing
checkout can charge the configured payment method.
Use a unique idempotency key for each intended order and a separate key for
checkout. If a response is lost, retry the same operation with the same key
and identical body. Do not reuse these illustrative keys for another purchase.
See [idempotency](/api/idempotency) for retention and conflicts.

## 3. Check what happened after checkout [#3-check-what-happened-after-checkout]

```bash title="Retrieve after the customer completes checkout"
api GET "/v2/orders/${SELLAPP_ORDER_ID}" \
  | jq '.data | {id, status, customer, totals, line_items}'
```

For this paid example, expect `data.payment.checkout_url`. A zero-priced checkout
can instead return `200` with a paid order and no URL; fulfillment may still be queued.
Do not redirect to an absent URL or mark the purchase complete based on a
browser return alone.

Use signed webhooks and retrieved state. `order.paid` records entry into the
paid state; `order.completed` records the completed order state, not completion
of every external task, such as granting access in your app.
See [Fulfil an order](/api/fulfil-an-order) for processing that can recover after a crash.


# Errors and retries (/docs/api/errors)



Start with the HTTP status to decide what to do next, then read the error body
for details. Store API errors use the same JSON structure. OAuth protocol
endpoints use OAuth error responses described in [OAuth authorization](/api/oauth-authorization).
Validation errors also
include an `errors` object listing every field that needs fixing.

```json title="Validation error"
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

Use `type` to group errors and `code` to choose a specific handling path in your
code. Read `message` for an explanation, but do not depend on its exact wording.
`param` names the first invalid field for a validation error and is otherwise
`null`. Keep `request_id` when asking support to investigate.

## Platform error codes [#platform-error-codes]

| Code                              | What it means                                                 | What to do                                                        |
| --------------------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------- |
| `idempotency_key_required`        | A side-effecting mutation has no key.                         | Add a unique `Idempotency-Key`.                                   |
| `idempotency_key_reused`          | The key was used with different input.                        | Create a new key for the new intent.                              |
| `idempotency_request_in_progress` | The first request is still running.                           | Wait briefly, then retry the identical request.                   |
| `cursor_expired`                  | A signed event cursor is outside the 30-day retention window. | Restart without the expired cursor and continue ordinary polling. |

`410` covers expired cursors and temporary resources. A `429` includes
`Retry-After`; `X-RateLimit-Reset` gives the Unix reset time.

## Recovery by status [#recovery-by-status]

| Status | Code                                              | Recovery                                                                                                   |
| ------ | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `400`  | `bad_request`                                     | Correct the request syntax or required headers. Do not retry unchanged input.                              |
| `401`  | `unauthenticated`                                 | Add, replace, or correctly format the bearer key.                                                          |
| `403`  | `forbidden`                                       | Check token abilities, store membership, and staff permissions.                                            |
| `404`  | `resource_not_found`                              | Verify the path, resource ID, and the slug in `X-STORE`. Cross-store resources intentionally look missing. |
| `409`  | `conflict`                                        | Retrieve the resource again and check whether your change still makes sense.                               |
| `410`  | `cursor_expired` or an expired temporary resource | Follow the response guidance. For events, restart cursor polling without the expired cursor.               |
| `422`  | `validation_failed`                               | Correct every field in `errors`; do not retry the same payload.                                            |
| `429`  | `rate_limit_exceeded`                             | Wait for `Retry-After`, then retry with exponential backoff and jitter.                                    |
| `5xx`  | `api_error`                                       | Retry reads and idempotent writes within a finite budget. Retain the request ID.                           |

<h3 id="bad-request">
  bad_request
</h3>

The server could not understand the request. A common
cause is omitting a header required by that route.

<h3 id="unauthenticated">
  unauthenticated
</h3>

The bearer key is missing, malformed, revoked, or unknown.

<h3 id="forbidden">
  forbidden
</h3>

The key is valid, but its abilities or the account's store permissions do not
authorize the operation.

<h3 id="resource-not-found">
  resource_not_found
</h3>

The route or resource was not found in the selected store. A resource belonging
to another store also looks missing; this keeps that store's information private.

<h3 id="conflict">
  conflict
</h3>

The request conflicts with the resource's current state. Retrieve it again and
make the change only if it is still allowed.

<h3 id="endpoint-gone">
  endpoint_gone
</h3>

The operation was retired. Read `x-sellapp-replacement` from its OpenAPI entry
or follow the [legacy v1 migration map](/api/legacy-v1).

<h3 id="validation-failed">
  validation_failed
</h3>

Inspect `errors`, fix the named fields, and send a new request. Reusing an
idempotency key with different input is also reported as validation failure by
the operations that support keys.

<h3 id="rate-limit-exceeded">
  rate_limit_exceeded
</h3>

The caller exceeded the API's minute window. See [Rate limits](/api/rate-limits).

<h3 id="api-error">
  api_error
</h3>

SellApp could not complete the operation. Log the request ID. Retry only if the
method is safe or the write uses documented idempotency.

## Retry example [#retry-example]

When a retry is safe, wait longer between attempts (**exponential backoff**)
and choose a random delay within that window (**full jitter**). This keeps all
your workers from retrying at the same instant:

```text
delay = random(0, min(30 seconds, 0.5 seconds × 2^attempt))
```

Honor `Retry-After` when it is present. Stop after a bounded number of attempts
or elapsed time, and include the final `request_id` in your error report.


# Fulfil an order (/docs/api/fulfil-an-order)



Register and test your webhook **before** creating the order or opening
checkout. For the Design kit example, match webhook `data.id`
with Maya's order `9001`. The top-level `id` identifies the delivery,
not the order.

## Payment is not the same as completed fulfillment [#payment-is-not-the-same-as-completed-fulfillment]

| Event             | What changed                                                             | What it does not prove                                                                |
| ----------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| `order.paid`      | SellApp entered the paid order state and queued fulfillment.             | Fulfillment or your external access grant has finished.                               |
| `order.completed` | SellApp entered its completed order state after its completion workflow. | Every external delivery, community grant, notification, or receiver job has finished. |

The order tracks the purchase as a whole; its line items track delivery for
each purchased product. Read the current order and relevant line
items when deciding which access to grant. A browser return is not evidence of
payment, and events can arrive out of order.

## Commit recoverable work before returning 2xx [#commit-recoverable-work-before-returning-2xx]

Think of your receiver as a reliable inbox: first save the event, then do the
work. If your app restarts, that saved event tells it what still needs doing.

Verify the exact raw body with a constant-time signature comparison, then
check that the payload has the expected fields and meets your event-age policy.
For each accepted event:

1. Begin a database transaction.
2. Insert an inbox row with a unique delivery `id`, the **full verified payload**,
   event/version, receipt time, and `pending` processing state.
3. Save that row and, if needed, a record of the work to send to a queue in the
   **same transaction**.
4. Return `2xx` only after the commit succeeds.
5. Let a background worker claim pending inbox rows, do the work safely even if retried, and
   mark each row processed only after that work succeeds.

A worker that checks the saved inbox rows does not need a separate queue message.
If you use a queue service, save a record of the message that still needs sending
with the inbox row, then send from that record.
This closes the gap where a crash could leave a saved event with no queued work.

Do **not** save only a deduplication ID, acknowledge, and then enqueue the payload.
A crash in that gap loses the work while making the retry look already handled.

On duplicate delivery, return `2xx` only if the original payload and recoverable
work were committed. Do not enqueue a second copy or treat `pending` as
`processed`. If storage is unavailable, return a failure so SellApp can retry.

## Recover after a crash [#recover-after-a-crash]

Workers need retries and a way to reclaim abandoned jobs. For example, a
time-limited claim (a **lease**) lets another worker take over after the original
one crashes. Move repeatedly failing jobs to a failed-job queue for inspection
and alert your team. Keep enough payload and progress information to resume safely.

Make the action itself safe to repeat (**idempotent**): use a stable operation key such as
`reading-room:9001:4321` for Maya's access grant, not only the delivery ID.
Separate events about the same purchase can have different delivery IDs. If
an external service succeeds but your worker crashes before marking the inbox
processed, retrying must not grant or charge twice. Use the external service's
idempotency support or check whether the action already happened there.

This pattern supports recoverable, idempotent processing; it does not promise
exactly-once execution across independent systems. Retrieve the current resource
before applying out-of-order events and do not undo completed work
because an older `order.paid` event arrived later.

## Reconcile missed or failed work [#reconcile-missed-or-failed-work]

Normal SellApp delivery makes at most ten attempts over roughly 75 hours. Your recovery plan should
include alerts for failed delivery, manual redelivery, and periodic checks that
your app agrees with SellApp's order state. Retries are durably scheduled, but
they are not indefinite. Test duplicates, reversed arrival order, database failure before commit,
and a worker crash after an external effect.

The invoice resource exposes fulfillment, dynamic-delivery, and notification
retry operations. Read current state first: these retry existing work and
should not create another purchase.

For signatures, acknowledgement deadlines, test events, and redelivery
controls, see [Webhooks](/api/webhooks).


# Handle subscriptions (/docs/api/handle-subscriptions)



Continue Maya's **Design kit membership** purchase. Use the integer SellApp
subscription ID from the purchased order line item (`55` in the illustrative responses), not
the provider's `sub_...` ID. These commands change real recurring billing;
run only against a subscription you are authorized to change.

## 1. Read capabilities [#1-read-capabilities]

Use Bash, cURL, `jq`, and a token with the `invoice` ability and corresponding
store permission. Replace the key, slug, order ID, and variant ID with your own values.
The subscription may be linked to the purchase a little later: if
`subscription_id` is still null, wait for the subscription event and retrieve again.

```bash title="Prepare the session and retrieve the subscription ID"
set -euo pipefail
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'
export SELLAPP_ORDER_ID='9001'
export SELLAPP_VARIANT_ID='4321'

api() {
  local method="$1" path="$2"
  shift 2
  curl --silent --show-error --fail-with-body \
    --request "$method" --url "${SELLAPP_API_BASE_URL}${path}" \
    --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
    --header "X-STORE: ${SELLAPP_STORE}" \
    --header 'Accept: application/json' \
    --dump-header /dev/stderr "$@"
}

SELLAPP_SUBSCRIPTION_ID=$(api GET "/v2/orders/${SELLAPP_ORDER_ID}" \
  | jq -er --argjson variant "$SELLAPP_VARIANT_ID" \
    '[.data.line_items[] | select(.product_variant_id == $variant) | .subscription_id | select(. != null)] | unique | if length == 1 then .[0] else error("Expected one subscription for this variant; inspect the order and subscription events.") end')
capabilities_json=$(api GET "/v2/subscriptions/${SELLAPP_SUBSCRIPTION_ID}/capabilities")
jq '.data.capabilities' <<< "$capabilities_json"
unset SELLAPP_PREVIEW_TOKEN
```

Capabilities tell you which actions this subscription supports and who can
perform them. A `200` response can include:

```json title="Capabilities — abbreviated, provider-dependent"
{"data":{"id":55,"subscription_id":"sub_design_kit_55","capabilities":{"shift_billing_date":{"status":"unsupported","seller_reason":"Stripe does not support arbitrary next-renewal-date changes for existing subscriptions through this provider flow."},"cancel_at_period_end":{"status":"available"},"change_plan":{"status":"customer_only"}}}}
```

If a capability is `unsupported`, `customer_only`, or otherwise not usable by
the seller, stop and read its reason. Provider capabilities and variant policy
both apply; an available capability does not override date or state restrictions.

The seller API's plan-change preview/confirm operations reject customer-owned
plan changes with `422`. Both current Stripe and PayPal provider flows also
report renewal-date changes as `unsupported`. Route availability does not mean
a provider implements the action. Do not put a seller key in a customer browser
to work around these boundaries.

For Maya's Stripe subscription, skip the renewal-date branches below and
[use the supported cancellation example](#4-cancel-a-disposable-subscription-deliberately).
The guarded preview/confirm code documents the complete exchange for a provider
that reports support; it is **not a successful Stripe or PayPal recipe**.

## 2. Preview a renewal-date change [#2-preview-a-renewal-date-change]

This block checks capability and skips the unsupported request for the current
Stripe/PayPal flows. If a future provider reports support, choose a future UTC
date permitted by the subscription's renewal-date policy.
The example date is illustrative; replace it before running if it is past or
outside the permitted shift window.

```bash title="Preview without confirming the billing change"
if jq -e '.data.capabilities.shift_billing_date.status | . == "available" or . == "seller_only"' \
  <<< "$capabilities_json" >/dev/null; then
  export SELLAPP_RENEWAL_DATE='2026-10-01T12:00:00Z'
  renewal_body=$(jq -nc --arg date "$SELLAPP_RENEWAL_DATE" '{
    renewal_date:$date,
    reason:"Align Maya with the next design-template cycle."
  }')
  preview_json=$(api POST "/v2/subscriptions/${SELLAPP_SUBSCRIPTION_ID}/actions/change-renewal-date/preview" \
    --header 'Content-Type: application/json' \
    --data "$renewal_body")
  SELLAPP_PREVIEW_TOKEN=$(jq -er '.data.preview_token' <<< "$preview_json")
  jq '.data | {expires_at, preview_payload, request_payload, customer_message, seller_message}' \
    <<< "$preview_json"
else
  printf '%s\n' 'Renewal-date changes are unsupported; no preview request was sent.'
fi
```

When supported, a `200` response supplies `data.preview_token`, `expires_at`,
`preview_payload`, and `request_payload`. Preview saves a token without
confirming the change. Review its actual billing effects and expiry.

Ignoring the current Stripe restriction can produce this `422` response
(selected fields; other policy or state failures can differ):

```json title="Unsupported Stripe renewal-date change — abbreviated"
{"type":"validation_error","code":"validation_failed","errors":{"subscription":["Stripe does not support arbitrary next-renewal-date changes for existing subscriptions through this provider flow."]}}
```

Do not retry that unchanged request. There is no success token to confirm.

## 3. Confirm the exact previewed input [#3-confirm-the-exact-previewed-input]

Run this block **only after reviewing and accepting the preview**. Preserve the
original renewal date and reason, and use the token returned for this subscription
and the account that requested it. A token cannot be reused for a different date or after expiry.

```bash title="Confirm with a stable key for this one logical change"
if [[ -n "${SELLAPP_PREVIEW_TOKEN:-}" ]]; then
  export SELLAPP_IDEMPOTENCY_KEY="design-kit-${SELLAPP_SUBSCRIPTION_ID}-renewal-${SELLAPP_PREVIEW_TOKEN}"
  confirm_body=$(jq -c --arg token "$SELLAPP_PREVIEW_TOKEN" \
    '. + {preview_token:$token}' <<< "$renewal_body")
  confirmation_json=$(api POST "/v2/subscriptions/${SELLAPP_SUBSCRIPTION_ID}/actions/change-renewal-date/confirm" \
    --header 'Content-Type: application/json' \
    --header "Idempotency-Key: ${SELLAPP_IDEMPOTENCY_KEY}" \
    --data "$confirm_body")
  jq '.data | {id, product_subscription_id, action, status, provider}' <<< "$confirmation_json"
else
  printf '%s\n' 'No supported preview was created; no confirmation request was sent.'
fi
```

Where supported, a successful `200` response means the action was saved.
The payment provider may still be processing it; check its status and later signed events.

The confirmation response contains `data.id` (action ID),
`data.product_subscription_id`, `data.action: "shift_billing_date"`, `data.status`,
and the actual provider name. The current Stripe/PayPal flows do not return
this successful renewal-date result.

After a timeout, retain `confirm_body` and `SELLAPP_IDEMPOTENCY_KEY` and retry
that exact confirmation. Do not create a new key for the same uncertain change.
A different change needs a new preview and key. Fix `422` policy or validation
errors before retrying; sending the same invalid input again will not help.

## 4. Cancel a disposable subscription deliberately [#4-cancel-a-disposable-subscription-deliberately]

Cancellation is optional and affects future billing. Check cancellation
capability first. This example schedules cancellation at the end of the current
period; it does not request an immediate refund.

```bash title="Schedule period-end cancellation"
api GET "/v2/subscriptions/${SELLAPP_SUBSCRIPTION_ID}/capabilities" \
  | jq -e '.data.capabilities.cancel_at_period_end.status | . == "available" or . == "seller_only"'

api PATCH "/v2/subscriptions/${SELLAPP_SUBSCRIPTION_ID}/cancel" \
  --header 'Content-Type: application/json' \
  --header "Idempotency-Key: design-kit-${SELLAPP_SUBSCRIPTION_ID}-cancel-v1" \
  --data '{"cancel_at_period_end":true}' | jq '.data'
```

The cancellation endpoint returns the subscription resource with `200`.

For immediate cancellation, refund flags request a separate financial effect. Cancellation can succeed even when its requested refund fails. A `200` or confirmed cancellation is not proof of a refund; check the order and payment provider refund records. The action response does not include the provider refund result. Do not replay cancellation as a refund-recovery step.
Keep the same key if this request loses its response. A future, distinct
cancellation needs a new key. See [Idempotency](/api/idempotency) for
where to send keys, how long they are kept, and what happens on a retry.


# Idempotency (/docs/api/idempotency)



A request can succeed even if your connection drops before the response arrives.
An **idempotency key** tells a supported endpoint, “This is the same change I
already asked for,” so retrying does not repeat that change.

Generate a hard-to-guess value such as a random UUID and save it with the change
you intend to make. Reuse that key only for the same operation with identical
inputs. A new change needs a new key.

## Supported operations [#supported-operations]

| Operation                                      | Transport                                                   | Required                 | Reuse behavior                                                                                               |
| ---------------------------------------------- | ----------------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------ |
| `POST /v2/affiliates/{affiliate}/payouts`      | `Idempotency-Key` header, max 100 characters                | Yes                      | Same affiliate returns the existing payout; another affiliate is rejected.                                   |
| `POST /v2/wallets/{customer}/adjustments`      | JSON `idempotency_key`, max 128                             | Yes                      | Identical input returns `200` with the existing ledger entry; different input is rejected.                   |
| `POST /v2/credit-transactions`                 | JSON `idempotency_key`, 1–128 characters                    | Yes                      | Identical input returns `200`; conflicting reuse and reserved internal prefixes are rejected.                |
| Subscription cancellation and lifecycle writes | `Idempotency-Key` header or JSON `idempotency_key`, max 128 | No, strongly recommended | The header takes precedence. A confirmed replay returns the persisted action; conflicting reuse is rejected. |

Keys are stored with the related ledger, payout, or subscription action. SellApp
does not currently expire these saved keys automatically, so do not recycle
them for another operation.

## Inherently idempotent operations [#inherently-idempotent-operations]

* `POST /v2/reward-grants` is unique per reward rule and customer. A repeat returns the existing grant.
* Updating an affiliate payout to the status it already has is a no-op.
* Fulfillment retry endpoints reset the same retryable effects instead of creating another effect.

These guarantees apply only to the listed operations. A write is not safe to
repeat just because another endpoint accepts an idempotency key.

## Replay rules [#replay-rules]

Operations that mark `Idempotency-Key` as required in their reference reject
requests without it. For operations using response replay, an identical retry returns the stored response with
`Idempotent-Replayed: true`. Different input returns
`409 idempotency_key_reused`; concurrent reuse returns
`409 idempotency_request_in_progress`.

Customer-session creation is the deliberate exception: its one-time plaintext
token and redemption URL are never cached or replayed.

Supported operations save successful results and return the existing resource
when you repeat the same request. Validation, authentication, authorization,
rate-limit, and server failures are not cached as idempotent successes.

If a connection fails after sending a keyed request, resend the exact method,
path, body, store slug, and key. Never generate a new key merely because the
first response was lost.

Set `SELLAPP_API_BASE_URL`, `SELLAPP_API_KEY`, and `SELLAPP_STORE` as shown
in [the quickstart](/api/quickstart#1-set-your-credentials).

```bash title="Idempotent affiliate payout"
curl --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliates/42/payouts" \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Idempotency-Key: 01992a65-e064-71ba-b38f-902b7966a6be' \
  --header 'Accept: application/json'
```


# CLI authorization (/docs/api/oauth-authorization)



Connect the official SellApp CLI to work with stores you already manage. OAuth
opens a browser for your approval and keeps access tokens out of command-line
arguments. SellApp does not offer customer registration, configuration, or
installation of third-party OAuth applications.

Consent can allow commands that read or change real store data. It never grants
additional store permissions: every request checks your current membership and
permissions as well as the approved stores, installation scopes, and token scopes.
Members can connect using their existing permissions. Owners manage membership
and roles normally; there is no separate owner approval or CLI blocking control.

## Log in and select a store [#log-in-and-select-a-store]

Use the [CLI build and setup guide](/api/cli), then run:

```bash
sellapp login
sellapp stores list
sellapp stores use launch-lab
sellapp products list --limit 1
```

Sign in in the browser, review the requested scopes, and select the stores to
connect. Declining consent leaves the connection unapproved. The CLI selects a
single available store automatically; when several stores are available, choose
one in the terminal or with `stores use`. `stores list` checks current access
instead of relying on a saved store list.

For a narrower read-only request, include `stores:read` for store discovery:

```bash
sellapp login --scopes "stores:read products:read"
```

The default request contains exactly these 17 scopes:

* `stores:read`
* `community:read`, `community:write`
* `customers:read`, `customers:write`
* `orders:read`, `orders:write`
* `payments:read`, `payments:write`
* `products:read`, `products:write`
* `store:read`, `store:write`
* `support:read`, `support:write`
* `webhooks:read`, `webhooks:write`

New CLI commands do not automatically add login permissions. A command outside
the approved scopes remains unavailable, even if your store role permits it.

Use `sellapp login --no-browser` when the CLI cannot open a browser. It prints an
authorization URL that you can open manually on the same computer. The callback
must reach the CLI's temporary local listener.

## Inspect or disconnect [#inspect-or-disconnect]

Open **CLI access** in your personal dashboard menu to see your connection,
currently accessible stores, and connection time when known. **Disconnect**
revokes your connection and its complete token family. You can still disconnect
after leaving every store. Store owners cannot disconnect another member's
personal CLI connection.

You can also disconnect the current profile from the terminal:

```bash
sellapp auth logout
```

Logout revokes the server connection before deleting the local credentials.
Removing a membership or restricting a role takes effect on subsequent requests;
it does not grant access through a previously approved consent screen.

## Token handling [#token-handling]

The CLI uses Authorization Code with PKCE S256: a fresh verifier binds the browser
approval to the process that started login. A random `state` value binds the
callback to that attempt. Its registered callback is
`http://127.0.0.1/callback`; the CLI chooses a temporary local port for each login.
The public client ID identifies the supported registration. It does not prove
that a request came from the official executable, and no client secret is embedded.

The OS credential vault stores the access and refresh tokens together. Refresh
rotates the pair under a process lock. The CLI does not retry a credential after
an uncertain exchange: a lost response may mean the server already used it.
Authorize again after an invalid grant or uncertain refresh. Never print tokens,
include them in URLs, or enable shell tracing around credentials.

The existing `/oauth/authorize`, `/oauth/token`, and `/oauth/revoke` protocol
endpoints support the official CLI. Their low-level SDK interfaces remain
available, but they are not an application registration service.

## Diagnose failures [#diagnose-failures]

| Error            | What to do                                                                                                                                                              |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `access_denied`  | Consent was declined. Start a new login only if you want to approve the connection.                                                                                     |
| `invalid_client` | Check that you are using the official CLI. Contact SellApp support if the error persists.                                                                               |
| `invalid_scope`  | Use a narrower `--scopes` request from the supported scopes above. Contact SellApp support if a listed scope is rejected; repeating the same login will not resolve it. |
| `invalid_grant`  | The code or refresh credential is expired, revoked, invalid, or already used. Start a new login.                                                                        |
| Store `403`      | Check the selected store, current membership, role permissions, and required scopes. Credentials remain available for other stores.                                     |

Keep the request ID when available. Share the error category, not credentials or
arbitrary OAuth response bodies.


# Pagination (/docs/api/pagination)



Long lists arrive in pages, not one huge response. Use `limit` for the number of items per page
and `page` for the page number. Standardized v2 operations default to 15 items
per page and reject limits above 100 with a `422` response.

Some operations document a different default or maximum. For example, variant
serial inventory defaults to 50 items and accepts up to 250. The limits shown on
the endpoint take precedence over the general defaults here.

Most operations accept `limit` and `page` as query parameters. Order and line
item search operations accept the same fields inside a `pagination` object in
the JSON request body.

The response calls the page size `meta.per_page`. Send `limit` in the request,
not `per_page`.

Follow `links.next` to get the next page. When it is `null`, you have reached
the end of the list.

When an operation supports `pagination=false`, the response omits pagination
links and metadata and returns a single `data` array. This does not request an
unlimited result set: standardized operations still return at most 100 items.

## Example using invoices [#example-using-invoices]

<Row>
  <Col>
    In this example, we request page `10` with a limit of `20` results per
    page. The response returns twenty invoices and the `last_page` attribute
    tells us we have not yet reached the end of the result set. The abbreviated
    response below shows only three of those twenty invoices and selected fields.

    <Properties>
      <Property name="limit" type="integer">
        The maximum number of items to return on one page.
      </Property>

      <Property name="page" type="integer">
        The page to retrieve, starting at `1`.
      </Property>
    </Properties>
  </Col>

  <Col>
    Set `SELLAPP_API_BASE_URL`, `SELLAPP_API_KEY`, and `SELLAPP_STORE` as shown
    in [the quickstart](/api/quickstart#1-set-your-credentials).

    ```bash title="Manual pagination using cURL"
    curl --request GET \
      --url "${SELLAPP_API_BASE_URL}/v2/invoices?page=10&limit=20" \
      --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
      --header "X-STORE: ${SELLAPP_STORE}" \
      --header 'Content-Type: application/json'
    ```

    ```json title="Paginated response — abbreviated to three invoices"
    {
      "data": [
        {
          "id": 181
        },
        {
          "id": 182
        },
        {
          "id": 183
        }
      ],
      "links": {
        "first": "https://sell.app/api/v2/invoices?page=1&limit=20",
        "last": "https://sell.app/api/v2/invoices?page=42&limit=20",
        "prev": "https://sell.app/api/v2/invoices?page=9&limit=20",
        "next": "https://sell.app/api/v2/invoices?page=11&limit=20"
      },
      "meta": {
        "current_page": 10,
        "from": 181,
        "last_page": 42,
        "links": [
          {
            "url": "https://sell.app/api/v2/invoices?page=9&limit=20",
            "label": "&laquo; Previous",
            "active": false
          },
          {
            "url": "https://sell.app/api/v2/invoices?page=10&limit=20",
            "label": "10",
            "active": true
          },
          {
            "url": "https://sell.app/api/v2/invoices?page=11&limit=20",
            "label": "Next &raquo;",
            "active": false
          }
        ],
        "path": "https://sell.app/api/v2/invoices",
        "per_page": 20,
        "to": 200,
        "total": 831
      }
    }
    ```
  </Col>
</Row>


# Make your first request (/docs/api/quickstart)

This request reads your catalog. It does not create a product or charge anyone.
You need a SellApp store and a server-side API key with the `listing` ability.
Create the key in your store's Developer settings. Keep it out of browser code
and source control. See [authentication](/api/authentication) for OAuth and permissions.

## 1. Set your credentials [#1-set-your-credentials]

Replace `replace-me` with your API key and `launch-lab` with your store slug.
Run these commands in a terminal with cURL installed:

```bash
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'
export SELLAPP_API_BASE_URL='https://sell.app/api'
```

The cURL and SDK programs below pass `SELLAPP_API_BASE_URL` explicitly.
Setting it alone does not configure every SDK.

## 2. List one product [#2-list-one-product]

```bash
curl --silent --show-error --fail-with-body \
  --url "${SELLAPP_API_BASE_URL}/v2/products?limit=1" \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Accept: application/json'
```

A successful request returns HTTP `200`. Read the `data` array in the JSON
response: it contains at most one product. Product IDs come from your store;
use the returned ID in later requests instead of copying an illustrative ID.

An empty store returns an empty `data` array. That is a successful request,
not an authentication problem. [Create your first product](/api/sell-a-product)
when you are ready.

## 3. If the request fails [#3-if-the-request-fails]

| Response         | What to do                                                                  |
| ---------------- | --------------------------------------------------------------------------- |
| `401`            | Check that your key is present, valid, and has not been revoked.            |
| `403`            | Check the key's `listing` ability and your permission to access this store. |
| `400` with OAuth | Supply `X-STORE` with the store you selected.                               |
| `429`            | Wait for the response's retry guidance before sending another request.      |

Keep the `X-Request-ID` response header when asking for help. Never share your
API key. See [errors](/api/errors) for the complete response format.

## Use an SDK or the CLI [#use-an-sdk-or-the-cli]

The [official SDKs](/api/sdks) cover TypeScript, Python, PHP, Go, .NET, Kotlin,
Ruby, Rust, and Elixir. Their first-request examples use the same environment
credentials. See [CLI setup](/api/cli) for installing the command-line tool.

Install the SDK for your language using its [source installation instructions](/api/sdks),
then run the matching complete program below. Each example makes the same catalog
read. The CLI reads `SELLAPP_API_BASE_URL`; `--base-url` overrides it.
SDK programs print the product or a successful empty-store message. The CLI
returns a JSON array when its output is redirected; `[]` means the read succeeded.

### Official TypeScript

```typescript
import { SellApp } from 'sellapp';

// 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!');

```

### Official Python

```python
import os

from sellapp_sdk import SellAppClient

base_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.")

```

### Official PHP

```php
<?php

declare(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;
}

```

### Official Go

```go
package main

import (
	"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)
	}
}

```

### Official .NET

```csharp
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;
        }
    }
}

```

### Official Kotlin

```kotlin
package sellapp.examples

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.exceptions.SellAppApiException
import app.sell.sellapp.common.exceptions.SellAppSerializationException
import app.sell.sellapp.common.exceptions.SellAppTimeoutException
import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient
import app.sell.sellapp.types.CatalogVisibility
import app.sell.sellapp.common.http.PatchField

fun 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()
    }
}

```

### Official Ruby

```ruby
# frozen_string_literal: true

require "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?

```

### Official Rust

```rust
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(())
}

```

### Official Elixir

```elixir
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!")

```

### Official CLI

```bash
sellapp products list --limit 1

```

## What next? [#what-next]

* [Create a product and variant](/api/sell-a-product).
* [Create an order checkout](/api/create-a-checkout).
* [Receive order events](/api/fulfil-an-order).
* [Advanced subscription checkout](/api/subscription-checkout), including provider setup and webhooks.

# Rate limits (/docs/api/rate-limits)



The authenticated API permits **60 requests per minute per authenticated
user**. Requests that cannot be associated with a user are limited by client IP
address.

Response headers tell you how much of that allowance remains:

* `X-RateLimit-Limit`: maximum requests in the minute.
* `X-RateLimit-Remaining`: requests left in the current minute.
* `Retry-After`: seconds to wait; present on a `429 Too Many Requests` response.
* `X-Request-ID`: identifier for this individual attempt.

Rate limits protect the service and can change as capacity and abuse controls
evolve. Treat the response headers, rather than a hard-coded timer, as
the source to follow.

## Handle 429 [#handle-429]

Pause requests until `Retry-After` has elapsed. If further retries are needed,
wait longer between attempts and add a random delay; this is **exponential
backoff with jitter**. Set a maximum number of attempts or a time limit. A `429` does not mean the write
ran successfully, but retry writes only when the operation is inherently
idempotent or uses a documented key.

To make fewer requests, cache data that rarely changes, avoid fetching the
same page repeatedly, and combine duplicate requests from your own workers.
Use webhooks for supported events instead of repeatedly asking whether
something changed.


# Request lifecycle (/docs/api/request-lifecycle)



Before an operation runs, SellApp checks who you are, which store you selected,
what your credential and account can do, and whether the request is valid. It also
applies rate limits and checks that the resource belongs to your store.

```text
API key or OAuth token → store selection → permissions → validation → operation → response
```

## Keep the request ID [#keep-the-request-id]

Every response includes a server-generated `X-Request-ID`. Error responses also
include the same value in `request_id`. Log it with the HTTP method, path,
status, duration, idempotency key, and your own business identifier. Do not log
the bearer key, webhook signing secret, payout destination, or sensitive
deliverables.

The request ID identifies one HTTP attempt. Retrying creates a new request ID.
An **idempotency key** has a different job: it identifies one intended change,
such as a payout, across all its retry attempts. Keep that key the same.

## Decide whether to retry [#decide-whether-to-retry]

* Retry `GET` requests after network failures, `429`, and transient `5xx` responses.
* Retry writes only when the operation is inherently idempotent or you supplied a documented idempotency key.
* Never retry an unchanged `400`, `401`, `403`, `404`, or `422` response.
* Honor `Retry-After` on `429`; otherwise use exponential backoff with jitter.
* Set a maximum number of attempts or a time limit for the whole operation.

If the connection fails after sending a non-idempotent write, read the related
resource or search by your business identifier before sending it again. A lost
response does not mean the change failed: the server may have finished it.

Continue with [Errors and retries](/api/errors), [Idempotency](/api/idempotency),
and [Rate limits](/api/rate-limits).


# Official SDKs and extensions (/docs/api/sdks)



You do not need an SDK to use SellApp: the cURL examples or your language's HTTP
client are enough. An SDK is a library that handles some of that request setup
for you.

## Official SDKs [#official-sdks]

SellApp provides generated clients for nine languages. Each client covers the
same included API operations and includes typed requests, response access,
pagination, errors, and executable examples.

Follow the installation instructions in your SDK's `README.md`, then use
the first-request examples below.

| Language             | Source repository name | First-request guide                |
| -------------------- | ---------------------- | ---------------------------------- |
| Node.js / TypeScript | `sellapp-node`         | `README.md` in the source checkout |
| Python               | `sellapp-python`       | `README.md` in the source checkout |
| PHP                  | `sellapp-php`          | `README.md` in the source checkout |
| Go                   | `sellapp-go`           | `README.md` in the source checkout |
| .NET                 | `sellapp-dotnet`       | `README.md` in the source checkout |
| Kotlin               | `sellapp-kotlin`       | `README.md` in the source checkout |
| Ruby                 | `sellapp-ruby`         | `README.md` in the source checkout |
| Rust                 | `sellapp-rust`         | `README.md` in the source checkout |
| Elixir               | `sellapp-elixir`       | `README.md` in the source checkout |

Start with [one read-only request](/api/quickstart), then use the generated
`docs/methods.md` resource index to find your next operation. Prefer terminal
commands? See [the official CLI](/api/cli).

## Community SDKs & extensions [#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.
</Note>

<Cards>
  <Card title="Node.js by t6c" href="https://github.com/t6c/sellapp-api-wrapper">
    A community-maintained Node.js wrapper for the SellApp API.
  </Card>

  <Card title="Python by qoft" href="https://github.com/qoft/sellapp">
    A community-maintained Python package for interacting with SellApp.
  </Card>

  <Card title=".NET by biitez" href="https://github.com/biitez/SellApp">
    A community-maintained .NET integration for SellApp.
  </Card>

  <Card title="React by 6ichem" href="https://github.com/6ichem/react-sellapp">
    A community-maintained React integration for SellApp storefront flows.
  </Card>
</Cards>

***

## Embedding SellApp products [#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](/embedding-products) guide
in the main help documentation.


# Sell a product (/docs/api/sell-a-product)



A product is what the customer sees; a variant is the option they buy. The
product holds the title and description, while each variant sets the price,
payment methods, stock, and delivery. This example creates **Design kit*&#x2A;, with a
**$19.99 one-time purchase** purchased by Maya in the checkout walkthrough.

## 1. Prepare credentials [#1-prepare-credentials]

Use Bash, cURL, and `jq`. Replace the key and store slug below. Your token needs
the `listing` ability and corresponding store permissions. These are real
records, not sandbox data; use a dedicated store with Stripe configured.
No payment is collected by these catalog requests.

```bash title="Run once in the same Bash session"
set -euo pipefail
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

api() {
  local method="$1" path="$2"
  shift 2
  curl --silent --show-error --fail-with-body \
    --request "$method" --url "${SELLAPP_API_BASE_URL}${path}" \
    --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
    --header "X-STORE: ${SELLAPP_STORE}" \
    --header 'Accept: application/json' \
    --dump-header /dev/stderr "$@"
}

api GET '/v2/products?limit=1' | jq '.data'
```

## 2. Create the product and variant [#2-create-the-product-and-variant]

`HIDDEN` keeps the product off normal storefront listings; it is not an
`is_draft` flag or a security boundary. The API rejects writes to `is_draft`.
Do not share checkout links until setup is complete.

```bash title="Create Design kit"
product_json=$(api POST /v2/products \
  --header 'Content-Type: application/json' \
  --data '{
    "title":"Design kit",
    "description":"Templates for your next project.",
    "visibility":"HIDDEN"
  }')
SELLAPP_PRODUCT_ID=$(jq -er '.data.id' <<< "$product_json")

variant_json=$(api POST "/v2/products/${SELLAPP_PRODUCT_ID}/variants" \
  --header 'Content-Type: application/json' \
  --data '{
    "title":"Standard",
    "description":"Design files delivered by our team.",
    "deliverable":{"types":["MANUAL"],"data":{"stock":null,"comment":"We will send your design files."}},
    "pricing":{"humble":false,"price":{"price":1999,"currency":"USD"}},
    "payment_methods":["STRIPE"]
  }')
SELLAPP_VARIANT_ID=$(jq -er '.data.id' <<< "$variant_json")
```

Both requests return `201`. Selected fields from their responses:

```json title="Product response — abbreviated"
{"data":{"id":120,"title":"Design kit","visibility":"HIDDEN","variants":[]}}
```

```json title="Variant response — abbreviated"
{"data":{"id":4321,"product_id":120,"title":"Standard","payment_methods":["STRIPE"]}}
```

USD amounts use cents: send `1999` for $19.99, not `19.99`. The variant
starts with a one-time price. The `MANUAL` deliverable means your team or
integration must send the design files; a successful API response does not
do that work for you.

## 3. Verify the result [#3-verify-the-result]

```bash title="Retrieve the product and variant"
api GET "/v2/products/${SELLAPP_PRODUCT_ID}" | jq '.data | {id, title, visibility}'
api GET "/v2/products/${SELLAPP_PRODUCT_ID}/variants/${SELLAPP_VARIANT_ID}" \
  | jq '.data | {id, title, pricing, payment_methods}'
```

Keep the IDs from your responses; `120` and `4321` are examples, not test resources you can reuse.
Send the most recently read `updated_at` as `expected_updated_at` when updating
the product to catch changes made since you last read it. Sensitive deliverables
are hidden or write-only, so keep your own secure copy; a read response is not a backup.

Creation has no general idempotency key. After a lost response, check whether
the product or variant was created before repeating a POST. Keep the product hidden until you
intend to list it, then change visibility deliberately.

Next, [create a checkout](/api/create-a-checkout), registering and testing your
webhook **before** order creation. For the full subscription integration, use
[the advanced walkthrough](/api/subscription-checkout).


# Advanced: subscription checkout (/docs/api/subscription-checkout)



Take one purchase all the way through: Maya Chen buys **Design kit membership*&#x2A;
for **$19.99 per month**. You will set up webhooks, create the product, and get
a checkout link. The commands carry returned IDs forward automatically;
the illustrative responses use product `120`, variant `4321`, order
`9001`, and SellApp subscription `55`. Your IDs will differ.

## 1. Prepare a dedicated store [#1-prepare-a-dedicated-store]

There is no separate SellApp API sandbox. These requests create real records
and payment-provider objects. Use a dedicated store, a configured Stripe
connection that supports subscriptions, and provider test credentials only
where your store's integration supports them. Do not complete a real payment
unless you intend to pay.

You need Bash, cURL for HTTP requests, `jq` for reading JSON, and a key with `listing`, `invoice`, and `webhook`
abilities. Subscription lifecycle requests also use `invoice`, not a separate
subscription ability. The account needs the corresponding store permissions.

Before continuing, deploy a receiver at a public HTTPS URL, configure the
store's signing secret in Developer settings, and securely give the same secret
to the receiver. Follow [the crash-safe receiver flow](/api/fulfil-an-order).
Keep secret keys out of browser code and source control.

```bash title="Run once in the same Bash session"
set -euo pipefail
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'
export SELLAPP_WEBHOOK_URL='https://your-server.example/sellapp/webhooks'

api() {
  local method="$1" path="$2"
  shift 2
  curl --silent --show-error --fail-with-body \
    --request "$method" --url "${SELLAPP_API_BASE_URL}${path}" \
    --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
    --header "X-STORE: ${SELLAPP_STORE}" \
    --header 'Accept: application/json' \
    --dump-header /dev/stderr "$@"
}

api GET '/v2/products?limit=1' | jq '.data'
```

Replace `replace-me` with your key, `launch-lab` with your store slug, and the
`.example` webhook URL with your own reachable endpoint. Expect `200` from the
read request; an empty array is valid. Response headers go to stderr so you can
retain `X-Request-ID` without corrupting the JSON output.

## 2. Register and test the webhook first [#2-register-and-test-the-webhook-first]

Do this **before creating an order or opening checkout**, otherwise you can
miss the events you want to observe. This creates a new channel; if the URL
already has a channel, retrieve it and update its filter instead.

```bash title="Register the receiver and prove it acknowledges a signed test"
channel_json=$(api POST /v2/webhook-channels \
  --header 'Content-Type: application/json' \
  --data "$(jq -nc --arg url "$SELLAPP_WEBHOOK_URL" '{
    name: "Design kit receiver",
    url: $url,
    allowed_notifications: ["order.created", "order.paid", "order.completed", "subscription.created"]
  }')")
SELLAPP_WEBHOOK_CHANNEL_ID=$(jq -er '.data.id' <<< "$channel_json")
jq -e '.data.signing_secret_configured == true' <<< "$channel_json"

api POST "/v2/webhook-channels/${SELLAPP_WEBHOOK_CHANNEL_ID}/test" \
  --header 'Content-Type: application/json' \
  --data '{"event":"order.created"}' | jq -e '.data.status == "delivered"'
```

The channel response is `201`. The test is `200` with `data.status: "delivered"`.
Confirm the receiver durably stored the test payload and pending work.
Test payload IDs are synthetic and will not match the sale below.

## 3. Create the product and variant [#3-create-the-product-and-variant]

`HIDDEN` keeps the product off normal storefront listings; it is not an
`is_draft` flag or a security boundary. The API rejects writes to `is_draft`.
Do not share checkout links until setup is complete.

```bash title="Create Design kit membership"
product_json=$(api POST /v2/products \
  --header 'Content-Type: application/json' \
  --data '{
    "title":"Design kit membership",
    "description":"New design templates each month.",
    "visibility":"HIDDEN"
  }')
SELLAPP_PRODUCT_ID=$(jq -er '.data.id' <<< "$product_json")

variant_json=$(api POST "/v2/products/${SELLAPP_PRODUCT_ID}/variants" \
  --header 'Content-Type: application/json' \
  --data '{
    "title":"Monthly membership",
    "description":"Monthly design files delivered by our team.",
    "deliverable":{"types":["MANUAL"],"data":{"stock":null,"comment":"We will send your design files."}},
    "pricing":{"humble":false,"price":{"price":1999,"currency":"USD"}},
    "payment_methods":["STRIPE"]
  }')
SELLAPP_VARIANT_ID=$(jq -er '.data.id' <<< "$variant_json")
```

Both requests return `201`. Selected fields from their responses:

```json title="Product response — abbreviated"
{"data":{"id":120,"title":"Design kit membership","visibility":"HIDDEN","variants":[]}}
```

```json title="Variant response — abbreviated"
{"data":{"id":4321,"product_id":120,"title":"Monthly membership","payment_methods":["STRIPE"]}}
```

## 4. Configure monthly recurring pricing [#4-configure-monthly-recurring-pricing]

The variant starts with a one-time price. This next request changes it to a
monthly subscription. USD amounts use cents: send `1999` for $19.99, not `19.99`.

```bash title="Set the recurring price before checkout"
api PUT "/v2/products/${SELLAPP_PRODUCT_ID}/variants/${SELLAPP_VARIANT_ID}/pricing" \
  --header 'Content-Type: application/json' \
  --data '{
    "pricing":{
      "type":"SUBSCRIPTION",
      "humble":false,
      "price":{"price":1999,"currency":"USD"},
      "frequency":{"value":1,"interval":"MONTH"}
    },
    "payment_methods":["STRIPE"]
  }' | jq -e '.data.pricing.type == "SUBSCRIPTION"'
```

Expect `200`. Resolve provider/configuration errors before continuing; do not
create the order with the initial one-time price by accident. The `MANUAL`
deliverable means your team or integration must give the customer design files;
a successful API response does not do that work for you.

## 5. Create Maya's order and checkout session [#5-create-mayas-order-and-checkout-session]

```bash title="Create the purchase and obtain its actual checkout URL"
order_json=$(api POST /v2/orders \
  --header 'Idempotency-Key: launch-lab-maya-order-001' \
  --header 'Content-Type: application/json' \
  --data "$(jq -nc --arg variant "$SELLAPP_VARIANT_ID" '{
    customer_email:"maya@example.com",
    payment_method:"STRIPE",
    product_variants:{($variant):{quantity:1}}
  }')")
SELLAPP_ORDER_ID=$(jq -er '.data.id' <<< "$order_json")

checkout_json=$(api POST "/v2/orders/${SELLAPP_ORDER_ID}/checkout" \
  --header 'Idempotency-Key: launch-lab-maya-checkout-001')
SELLAPP_CHECKOUT_URL=$(jq -er '.data.payment.checkout_url' <<< "$checkout_json")
printf '%s\n' "$SELLAPP_CHECKOUT_URL"
```

Order creation returns `201`; checkout returns `201` for a new payment session
or `200` when reusing an existing session. Both return an order
under `data` and include `data.payment.checkout_url` when a URL is available.

```json title="Order response — abbreviated"
{"data":{"id":9001,"status":"PENDING","customer":{"email":"maya@example.com"},"payment":{"checkout_url":"https://checkout.stripe.com/c/pay/cs_example"},"totals":{"currency":"USD","total_cents":1999}}}
```

```json title="Checkout response — abbreviated, illustrative URL"
{"data":{"id":9001,"status":"PENDING","payment":{"checkout_url":"https://checkout.stripe.com/c/pay/cs_example"}}}
```

Open the URL printed by your request, not the illustrative URL above. Completing
checkout can charge the configured payment method and start recurring billing.
Use a unique idempotency key for each intended order and a separate key for
checkout. If a response is lost, retry the same operation with the same key
and identical body. Do not reuse these illustrative keys for another purchase.
See [idempotency](/api/idempotency) for retention and conflicts.

## 6. Verify payment, completion, and subscription [#6-verify-payment-completion-and-subscription]

A selected portion of the signed `order.completed` payload can look like this:

```json title="Order webhook — abbreviated; verify the full raw body"
{
  "id":"01992a65-e064-71ba-b38f-902b7966a6be",
  "created_at":"2026-08-30T12:05:00.000000Z",
  "event":"order.completed",
  "version":"1",
  "store":1,
  "data":{"id":9001,"subscription_id":55,"customer_information":{"email":"maya@example.com"}}
}
```

The top-level `id` identifies the delivery; `data.id` identifies the order.
Match `data.id` with `SELLAPP_ORDER_ID`. Events can arrive out of order, and
the subscription may be linked to the purchase a little later. Retrieve the order again:

```bash title="Read back the purchase after checkout"
api GET "/v2/orders/${SELLAPP_ORDER_ID}" \
  | jq '.data | {id, customer, status, line_items}'
```

`order.paid` means the order entered the paid state and fulfillment was queued.
`order.completed` means SellApp entered its completed order state; it does not
prove your receiver's work or every external notification has finished.
Track processed delivery IDs so a repeated event does not repeat the work.
Also make granting access safe to retry for the same order and variant.

Find the purchased variant in `data.line_items` by `product_variant_id`.
After its `subscription_id` becomes available, use that **integer SellApp ID**
(`55` here), not a provider ID like `sub_...`, in
[the subscription lifecycle walkthrough](/api/handle-subscriptions). Review and
cancel disposable recurring test subscriptions so they do not renew.


# Testing safely (/docs/api/testing)



SellApp does not expose a separate API sandbox or test-mode base URL. Every
request to `https://sell.app/api` reads or changes the real data of the store
selected by `X-STORE`.

## Keep test data separate [#keep-test-data-separate]

Use a dedicated, non-public store for integration testing. Give its API key
only the abilities under test, configure payment providers with their sandbox
credentials where supported, and use fictional customer addresses. Never reuse
a production webhook signing secret in the test store.

Keep the store slug in environment configuration so a deployment cannot switch
stores accidentally:

```dotenv
SELLAPP_API_BASE_URL=https://sell.app/api
SELLAPP_STORE=launch-lab
SELLAPP_API_KEY=replace-me
```

Before a test that changes data, check the store slug in your configuration and
make a read request. Confirm you are working in the intended store. Resources
from another store return `404`, so a request cannot reveal another store's data.

## Failures you can test on purpose [#failures-you-can-test-on-purpose]

A useful test checks more than the happy path. These cases give your error
handler a predictable response to work with:

| Case                 | Request                                               | Expected result                                            |
| -------------------- | ----------------------------------------------------- | ---------------------------------------------------------- |
| Missing key          | Omit `Authorization` from `GET /v2/products`          | `401`, code `unauthenticated`                              |
| Unknown store        | Use a guaranteed-unknown `X-STORE` slug               | `404`, code `resource_not_found`                           |
| Missing ability      | Use a read-only token on a documented write operation | `403`, code `forbidden`                                    |
| Unknown resource     | Retrieve an impossible current-store resource ID      | `404`, code `resource_not_found`                           |
| Invalid input        | Omit a required field from a write request            | `422`, code `validation_failed`, with `param` and `errors` |
| Idempotency conflict | Reuse a supported key with different input            | `422`, with the idempotency field named in `errors`        |

Do not deliberately trigger the shared production rate limit in routine tests.
Unit-test your `429` handler with a recorded response instead.

## Test webhooks [#test-webhooks]

Use a webhook channel's test operation to send a real signed delivery. Check
that the receiver verifies the exact raw body with a constant-time signature
comparison and saves the **full payload and recoverable pending work** before
returning `2xx`. Send a duplicate to check that it does not create duplicate
work. Saving only the event ID is not enough to recover after a crash.

Test deliveries make one attempt and report the result immediately. Normal deliveries are queued and
follow the retry behavior in the [webhook guide](/api/webhooks).

## Clean up [#clean-up]

Record every created ID and delete disposable catalog data where the API
supports deletion. Keep invoices, orders, ledger entries, and payout records as
audit history; isolate those tests with a fresh customer or store instead of
trying to erase them.


# Versioning and deprecations (/docs/api/versioning)



The version in the URL tells you which API contract a request uses. Start with `/v2` for new
integrations. Active `/v1` operations remain documented where no v2 replacement
exists or compatibility is still supported.

The OpenAPI document has its own `info.version`: the release date of that
document, not a URL version. One document can describe both `/v1` and `/v2`
endpoints. Do not copy its release date into your request path.

## Compatibility policy [#compatibility-policy]

Within an active URL version, SellApp may add optional request fields, response
fields, enum values, endpoints, events, or error detail. Human-readable messages
and protective rate limits can also change. Clients must ignore unknown response
fields and handle unknown enum values safely.

Breaking changes are changes that can require you to update working code.
Removing or renaming a field, changing its type or meaning, making optional
input required, or changing an operation's core side effect requires a new URL
version or a documented migration window.

## Deprecation lifecycle [#deprecation-lifecycle]

Deprecated operations have `deprecated: true` in OpenAPI and an
`x-sellapp-replacement` value naming the replacement method and path. Retired
operations return `410 Gone`; they remain in the contract so tooling can explain
the failure.

The legacy v1 listing and invoice operations are retired in favor of v2 product
and invoice operations. Other v1 resources are not automatically deprecated
merely because their path contains `/v1`.

Review the [API changelog](/api/api-changelog). A JSON feed is available at
[`/api-changelog.json`](/api-changelog.json) for automated filtering.


# Webhooks (/docs/api/webhooks)



Instead of repeatedly asking whether an order changed, let SellApp tell you.
A webhook is an HTTP request sent to your application when an event happens,
such as an order completing or a support ticket receiving a message.

## Registering webhooks [#registering-webhooks]

To register a webhook, you need a URL in your application that SellApp can call.
You can configure a new webhook from your storefront developers settings under
[the developers tab](https://sell.app/dashboard/settings?settings=developers).

Add your callback URL, pick the [events](#event-types) you want to listen for,
and save the webhook. Whenever one of those events happens, SellApp will send a
webhook request to your endpoint.

You can also manage destinations programmatically with the [Webhook Channels
API](/api/webhook-channels). Channels use stable UUIDs, reject private-network
destinations, and support safe one-attempt test deliveries.

## Consuming webhooks [#consuming-webhooks]

When your app receives a webhook request from SellApp, inspect the `event`
attribute to see what triggered it. The first part of the event type tells you
the payload category, such as an order or product.

Webhook channel configuration, search, and test requests use these same public
event names. For example, selecting `order.created` enables delivery and testing
of `order.created` payloads. SellApp keeps the corresponding internal
notification subscription private.

```json title="Example webhook payload"
{
  "id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "created_at": "2026-08-30T14:37:29.000000Z",
  "event": "order.completed",
  "version": "1",
  "data": {
    "id": 236
  },
  "store": 1
}
```

Here, `event` tells you what happened and `data.id` tells you which order it
happened to. The example shows only selected order fields.

`id` identifies the delivery. Automatic retries and manual redelivery preserve
it, so save it with the full payload under a database uniqueness constraint
before processing. `created_at` is the
time the delivery was created, not necessarily the time the underlying resource
was last updated.

Order webhook payloads include `customer_information`. When available, this object now includes `discord_data` for Discord-linked purchases and `billing_details` for billing details captured during checkout.

Order webhook payloads can include product variants whose `deliverable.types` contains `CREDITS`. For credits with fractional unit prices, SellApp may normalize `invoice_payment.payment_details` to `quantity: 1` and `unit_price` equal to the line subtotal so the webhook remains compatible with integer minor-unit payment fields.

## Delivery behavior [#delivery-behavior]

Seller webhook events are delivered asynchronously. Your endpoint must return
any `2xx` status within **30 seconds**. Save the full payload and recoverable
pending work before responding, then process it in the background;
do not wait for email, fulfillment, or third-party API calls.

Normal deliveries make at most **ten attempts over roughly 75 hours**. A timeout,
network failure, redirect, or non-2xx response fails the attempt. SellApp records
the next attempt durably and a scheduler dispatches it when due. The delay grows
between attempts with jitter; a valid `Retry-After` value on a throttled or
temporarily unavailable response can set the next delay. Test deliveries make
one synchronous attempt so the dashboard or API can report the result immediately.

Retries can deliver the same event more than once, and event ordering is not
guaranteed. Delivery can also fail after the final attempt; monitor failures and
check for missed work. A later resource state can arrive before an earlier one.
Deduplicate on the top-level `id`, then compare
the resource state in `data` with the state your application has already
processed.

New events include a string `version`. A new version can change the event's
payload contract; branch on `event` and `version`, tolerate additive fields,
and retain a safe fallback for an unknown version. Historical deliveries can
omit metadata added after they were first sent.

***

## Event types [#event-types]

<Row>
  <Col>
    <Properties>
      <Property name="cash_app.payment_requires_attention">
        A CashApp payment is pending.
      </Property>

      <Property name="charge.created">
        A new charge was created.
      </Property>

      <Property name="charge.completed">
        A charge was completed.
      </Property>

      <Property name="charge.disputing">
        A charge entered the dispute flow.
      </Property>

      <Property name="charge.disputed">
        A charge was disputed.
      </Property>

      <Property name="charge.partial_paid">
        A charge received a partial payment.
      </Property>

      <Property name="charge.review">
        A charge was marked for review.
      </Property>

      <Property name="charge.refunded">
        A charge was refunded.
      </Property>

      <Property name="charge.voided">
        A charge was voided.
      </Property>

      <Property name="feedback.created">
        A customer left feedback.
      </Property>

      <Property name="order.created">
        A new order was created.
      </Property>

      <Property name="order.paid">
        The order entered the paid state and fulfillment was queued. Delivery
        work may still be pending.
      </Property>

      <Property name="order.completed">
        The order entered its completed state. External access grants,
        notifications, and your receiver's business work may still be pending.
      </Property>

      <Property name="order.disputed">
        A paid order was disputed.
      </Property>

      <Property name="order.manual_payment_completed">
        A customer submitted completion details for a manual payment.
      </Property>

      <Property name="order.partial_paid">
        An order received a partial payment.
      </Property>

      <Property name="product.created">
        A new product was created.
      </Property>

      <Property name="product.updated">
        An existing product was updated.
      </Property>

      <Property name="product.trashed">
        A product was successfully deleted.
      </Property>

      <Property name="subscription.created">
        A product subscription was created.
      </Property>

      <Property name="subscription.renewed">
        A product subscription was renewed.
      </Property>

      <Property name="subscription.cancelled">
        A product subscription was cancelled.
      </Property>

      <Property name="ticket_message.created">
        A new ticket message was created.
      </Property>

      <Property name="variant.created">
        A new product variant was created.
      </Property>

      <Property name="variant.updated">
        An existing product variant was updated.
      </Property>

      <Property name="variant.sold_out">
        An existing product variant ran out of stock.
      </Property>
    </Properties>
  </Col>

  <Col>
    ```json title="Example payload"
    {
      "id": "01992a65-e064-71ba-b38f-902b7966a6be",
      "created_at": "2026-08-30T14:37:29.000000Z",
      "event": "ticket_message.created",
      "version": "1",
      "data": {
        "author": "CUSTOMER",
        "sender": "maya@example.com",
        "content": "Could you help me access the founder memo?",
        "ticket_id": 1337,
        "updated_at": "2026-08-30T13:37:29.000000Z",
        "created_at": "2026-08-30T13:37:29.000000Z",
        "id": 6969,
        "ticket": {
          "id": 1337,
          "title": "Design kit",
          "status": "OPEN",
          "customer": {
            "id": "c4e45131-a187-3476-9efd-1fb6fbbf2243",
            "email": "maya@example.com"
          },
          "reference": {
            "id": 87654,
            "type": "App\\Models\\Invoice"
          },
          "created_at": "2026-08-30T13:37:29.000000Z",
          "updated_at": "2026-08-30T13:37:29.000000Z",
          "store_id": 1,
          "read_by": 1,
          "archived": 0
        }
      },
      "store": 1
    }
    ```
  </Col>
</Row>

### VAT on order webhook payloads [#vat-on-order-webhook-payloads]

Order webhook payloads describe VAT twice, in `customer_information` and in each customer's `pivot`. Here is a 19% VAT charged on a $10.00 order:

```json title="Example order VAT — selected object fields"
{
  "vat": { "id": "DE123456789", "amount": 19, "country": "DE" },
  "vat_details": { "rate": "19", "amount": "190", "id": "DE123456789", "country": "DE" }
}
```

<Properties>
  <Property name="vat_details" type="object | null">
    The charged VAT. `rate` is the VAT percentage, `amount` is the VAT charged in minor
    units — the $1.90 here — and `country` is the customer's VAT country, `null` when
    unknown. The whole object is `null` when the order charged no VAT.
  </Property>

  <Property name="vat" type="object | null">
    The legacy VAT object: its `amount` is the VAT percentage, not money. It stays
    unchanged so existing integrations keep working — read `vat_details` instead.
  </Property>
</Properties>

### Charge webhook payloads [#charge-webhook-payloads]

Charge webhook payloads use the same top-level shape as other webhooks:
`event`, `data`, and `store`.

```json title="Example charge webhook payload"
{
  "id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "created_at": "2026-08-30T14:37:29.000000Z",
  "event": "charge.completed",
  "version": "1",
  "data": {
    "status": "COMPLETED",
    "id": 1234,
    "email": "maya@example.com",
    "payment_method": "STRIPE",
    "currency": "USD",
    "total": 49.99,
    "coupon": null,
    "reference": "External order #1001",
    "description": "One-time setup charge",
    "return_url": "https://example.com/thank-you",
    "gateway_data": {
      "transaction_id": "pi_123"
    }
  },
  "store": 1
}
```

***

## Security [#security]

To verify that a webhook came from SellApp, validate its signature before
parsing or processing the event. To create a webhook signing secret,
navigate to your [storefront developers settings](https://sell.app/dashboard/settings?settings=developers),
click **New Secret**, and save it.

New outbound deliveries also follow the [Standard Webhooks
format](https://github.com/standard-webhooks/standard-webhooks/blob/main/spec/standard-webhooks.md):

* `webhook-id` is the stable integration-event ID.
* `webhook-timestamp` is the Unix timestamp used for this attempt.
* `webhook-signature` contains `v1,<base64(HMAC-SHA256(...))>`.

Build the signing input as `id.timestamp.rawBody`, using the header values and
the exact raw body bytes. A retry or replay keeps the event ID but gets a new
timestamp and signature. Check the timestamp against your replay window, then
compare the decoded signature in constant time.

The legacy payload and `Signature` header remain supported unchanged. For that
scheme, calculate HMAC SHA-256 over
the **exact raw request body bytes** using the webhook secret. Do not parse and
re-serialize JSON before verification because key order or whitespace changes
the signature value. Compare signatures in **constant time**: use your language's
secure comparison function, as below, rather than ordinary string equality.
This avoids revealing matching portions through comparison timing.

<CodeBlockTabs defaultValue="js">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="js">
      JavaScript
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="python">
      Python
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="php">
      PHP
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="js">
    ```js
    const signature = req.headers['signature'] ?? '';
    const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
    const signatureBytes = Buffer.from(signature, 'hex');
    const expectedBytes = Buffer.from(expected, 'hex');
    const valid = signatureBytes.length === expectedBytes.length
      && crypto.timingSafeEqual(signatureBytes, expectedBytes);

    if (valid) {
      // Request has been verified
    } else {
      // Request could not be verified
    }
    ```
  </CodeBlockTab>

  <CodeBlockTab value="python">
    ```python
    from flask import request
    import hashlib
    import hmac

    signature = request.headers.get("signature")
    expected = hmac.new(secret.encode("utf-8"), raw_body, hashlib.sha256).hexdigest()

    if hmac.compare_digest(expected, signature or ""):
        # Request has been verified
    else:
        # Request could not be verified
    ```
  </CodeBlockTab>

  <CodeBlockTab value="php">
    ```php
    $signature = $request['headers']['signature'];
    $hash = hash_hmac('sha256', $rawBody, $secret);

    if (hash_equals($hash, $signature)) {
      // Request has been verified
    } else {
      // Request could not be verified
    }
    ```
  </CodeBlockTab>
</CodeBlockTabs>

A matching signature shows that the body was signed with your webhook secret.
Keep that secret safe: anyone who has it can sign a request. A valid signature
alone does not tell you whether you already processed the event.

## Replay protection and processing [#replay-protection-and-processing]

After signature verification, reject malformed or unexpectedly old payloads
according to your risk policy, then durably store the top-level `id`, full
verified payload, and pending processing state. Retain processed IDs for at
least as long as your business records need
to prevent duplicate side effects; SellApp does not impose a receiver-side
retention window.

Use a database uniqueness constraint rather than an in-memory cache alone.
Return a 2xx response for a duplicate only when the original payload and
recoverable work have committed. For a new ID, commit the payload and pending
inbox row before acknowledging. The inbox is your database record of work
still to do. A worker can read it directly; if you use a separate queue service,
save a record of the message to send in the same transaction
and send from it. Saving only the ID and enqueueing after acknowledgement can lose work
on a crash. See [Fulfil an order](/api/fulfil-an-order) for the full recovery flow.

The event timestamp is signed as part of the body, but the signature itself
does not contain a separate freshness window. Your receiver is responsible for
the acceptable age policy.

## Test and redeliver [#test-and-redeliver]

Use the Webhook Channels API test operation or the dashboard test control to
send a representative signed event to a current channel. The recent-deliveries
view can queue a manual redelivery to that channel. Redelivery preserves the
payload ID for deliveries created with the current contract, so the same
duplicate-delivery handling is tested.

## Discord webhooks and email notifications [#discord-webhooks-and-email-notifications]

Traditional webhook delivery cannot be used to post directly into a Discord
channel. Instead, go to your [store notifications settings](https://sell.app/dashboard/settings?settings=notifications)
and configure your Discord webhook URL there.

Discord and email notification settings use a broader notification catalog than
traditional webhook channels. Do not assume every notification key has a public
webhook event; use the Webhook Channels API's `allowed_notifications` enum as
the authoritative list. For setup instructions, see the [creating
notifications](/creating-notifications) guide.


# Community connections (/docs/api/community-connections)

Connect a supported community platform to your store. Connection and verification can contact the provider; a successful request does not prove every access grant has finished.

## Additional endpoint reference [#additional-endpoint-reference]

## GET /v2/community-connections

List community connections

List Discord, Telegram, Slack, and WhatsApp connection and persisted health status for the authenticated store without contacting providers. Credentials and provider secrets are never returned. Requires the `community` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.communityConnections.list();
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.community_connections.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->communityConnections()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.CommunityConnections().List(context.Background())
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CommunityConnections.ListAsync();
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.communityConnections.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.community_connections.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::community_connections::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.community_connections().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CommunityConnections.list(client)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp community-connections list

```

- Method: `GET`

- Path: `/v2/community-connections`

- Full URL: `https://sell.app/api/v2/community-connections`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `community:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/community-connections" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "platform": {
            "type": "string",
            "enum": [
              "discord",
              "telegram",
              "slack",
              "whatsapp"
            ]
          },
          "label": {
            "type": "string"
          },
          "configured": {
            "type": "boolean",
            "readOnly": true
          },
          "healthy": {
            "type": "boolean",
            "readOnly": true
          },
          "credential_health_status": {
            "type": [
              "string",
              "null"
            ],
            "readOnly": true,
            "description": "Provider credential health for an existing connection. This contributes to its overall connection status."
          },
          "credential_health_checked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "readOnly": true
          },
          "pending_grant_count": {
            "type": "integer",
            "minimum": 0,
            "readOnly": true
          },
          "failed_grant_count": {
            "type": "integer",
            "minimum": 0,
            "readOnly": true
          },
          "issues": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "readOnly": true
          },
          "accounts": {
            "type": "array",
            "readOnly": true,
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "username": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "display_name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "avatar_url": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uri"
                }
              },
              "required": [
                "id",
                "username",
                "display_name",
                "avatar_url"
              ]
            }
          },
          "servers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "type": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "health_status": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "readOnly": true
                },
                "health_checked_at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time",
                  "readOnly": true
                },
                "roles": {
                  "type": "array",
                  "readOnly": true,
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "color": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "name",
                      "color"
                    ]
                  }
                }
              },
              "required": [
                "id",
                "name",
                "type",
                "health_status",
                "health_checked_at",
                "roles"
              ]
            },
            "readOnly": true
          }
        },
        "required": [
          "platform",
          "label",
          "configured",
          "healthy",
          "credential_health_status",
          "credential_health_checked_at",
          "pending_grant_count",
          "failed_grant_count",
          "issues",
          "accounts",
          "servers"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "platform": "discord",
      "label": "Project Community",
      "configured": true,
      "healthy": true,
      "credential_health_status": "healthy",
      "credential_health_checked_at": "2026-08-30T09:41:00Z",
      "pending_grant_count": 0,
      "failed_grant_count": 0,
      "issues": [],
      "accounts": [
        {
          "id": "creator_2048",
          "username": "barques_reviews",
          "display_name": "Ella Robinson",
          "avatar_url": "https://example.com/avatars/barques.png"
        }
      ],
      "servers": [
        {
          "id": "server_ship_room",
          "name": "The Ship Room",
          "type": "server",
          "health_status": "healthy",
          "health_checked_at": "2026-08-30T09:41:00Z",
          "roles": [
            {
              "id": "role_01",
              "name": "Actually Shipped",
              "color": "#22c55e"
            }
          ]
        }
      ]
    }
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/community-connections/{platform}/connect

Start a community connection

Start the provider-specific connection flow. OAuth providers return a connect URL containing encrypted state bound to the authenticated actor, store, platform, and purpose; that state expires after 15 minutes and securely authorizes the provider callback without forwarding the API bearer token or requiring a SellApp dashboard session. Open the URL exactly as issued, then poll the connection list with the original bearer token after the provider redirects. Do not append credentials, reconstruct, or reuse the URL. Legacy unsigned Slack URLs are rejected, so clients must call this endpoint again to restart those flows. Telegram returns a short-lived verification token, and WhatsApp returns a pollable QR session. The provider application must be configured, and Discord server connections require a connected Discord account. Requires the `community` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.communityConnections.start({
  "platform": "discord",
  "mode": "official_bot"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.community_connections.start(
    platform="discord",
    mode="official_bot"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->communityConnections()->start(
    platform: 'discord',
    mode: 'official_bot',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CommunityConnectionsStartParams{}
    if err := json.Unmarshal([]byte("{\"mode\":\"official_bot\"}"), params); err != nil { panic(err) }
    result, err := client.CommunityConnections().Start(context.Background(), "discord", params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CommunityConnections.StartAsync(
    "discord",
    new CommunityConnectionsStartOptions
    {
        Mode = JsonConvert.DeserializeObject<SdkStartCommunityConnectionRequestApplicationJsonMode>("\"official_bot\"")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.communityConnections.start(platform = "discord", mode = app.sell.sellapp.types.SdkStartCommunityConnectionRequestApplicationJsonMode("official_bot"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.community_connections.start(
  platform: "discord",
  mode: "official_bot"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::community_connections::StartParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = StartParams::new(serde_json::from_str("{\"mode\":\"official_bot\"}")?);
    let result = client.community_connections().start("discord", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CommunityConnections.start(client, "discord", %{"mode" => "official_bot"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp community-connections start discord --mode official_bot --yes

```

- Method: `POST`

- Path: `/v2/community-connections/{platform}/connect`

- Full URL: `https://sell.app/api/v2/community-connections/{platform}/connect`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `community:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PLATFORM_ID='discord'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/community-connections/${SELLAPP_PLATFORM_ID}/connect" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "mode": "official_bot"
}'
```

## Path Parameters
- `platform` (`string`, required): The community platform.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "mode": {
      "type": "string",
      "enum": [
        "account",
        "official_bot",
        "custom_bot"
      ],
      "description": "Discord-only connection mode."
    }
  }
}
```

Example:

```json
{
  "mode": "official_bot"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "platform": {
          "type": "string",
          "enum": [
            "discord",
            "telegram",
            "slack",
            "whatsapp"
          ]
        },
        "type": {
          "type": "string",
          "enum": [
            "oauth",
            "verification_code",
            "qr"
          ]
        },
        "mode": {
          "type": "string"
        },
        "connect_url": {
          "type": "string",
          "format": "uri",
          "description": "Short-lived provider authorization URL containing protected OAuth state. The provider callback does not need the API bearer token or a dashboard session. Use exactly as returned; do not append credentials, reconstruct, or reuse it."
        },
        "verification_token": {
          "type": "string",
          "x-sensitive": true,
          "description": "Short-lived Telegram verification token to post in the target group."
        },
        "status_token": {
          "type": "string",
          "x-sensitive": true,
          "description": "Encrypted, store-bound token used to poll Telegram or WhatsApp connection state."
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "bot_username": {
          "type": [
            "string",
            "null"
          ]
        },
        "qr_code": {
          "type": "string",
          "x-sensitive": true
        }
      },
      "required": [
        "platform",
        "type"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "platform": "discord",
    "type": "oauth",
    "mode": "official_bot",
    "connect_url": "https://discord.com/oauth2/authorize?client_id=123456789012345678&scope=bot&state=example-state"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/community-connections/{platform}/status

Poll a community connection

Poll a pending Telegram verification or WhatsApp QR connection using the encrypted status token returned by the connect operation. Tokens are bound to the authenticated store and initiating user. Requires the `community` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.communityConnections.poll({
  "platform": "discord",
  "statusToken": "string_example"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.community_connections.poll(
    platform="discord",
    status_token="string_example"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->communityConnections()->poll(
    platform: 'discord',
    statusToken: 'string_example',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CommunityConnectionsPollParams{}
    if err := json.Unmarshal([]byte("\"string_example\""), &params.StatusToken); err != nil { panic(err) }
    result, err := client.CommunityConnections().Poll(context.Background(), "discord", params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CommunityConnections.PollAsync(
    "discord",
    new CommunityConnectionsPollOptions
    {
        StatusToken = "string_example",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.communityConnections.poll(platform = "discord", statusToken = "string_example")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.community_connections.poll(
  platform: "discord",
  status_token: "string_example"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::community_connections::PollParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = PollParams::new("string_example");
    let result = client.community_connections().poll("discord", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CommunityConnections.poll(client, "discord", %{"status_token" => "string_example"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp community-connections poll discord --status-token test_status_token

```

- Method: `GET`

- Path: `/v2/community-connections/{platform}/status`

- Full URL: `https://sell.app/api/v2/community-connections/{platform}/status`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `community:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PLATFORM_ID='discord'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/community-connections/${SELLAPP_PLATFORM_ID}/status?status_token=replace-me" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `platform` (`string`, required): The community platform.

## Query Parameters
- `status_token` (`string`, required): No description provided.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "platform": {
          "type": "string",
          "enum": [
            "telegram",
            "whatsapp"
          ]
        },
        "status": {
          "type": "string",
          "enum": [
            "pending",
            "used",
            "linked",
            "expired",
            "authenticated",
            "error",
            "unknown"
          ]
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "qr_code": {
          "type": [
            "string",
            "null"
          ],
          "x-sensitive": true
        },
        "server": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "type": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "health_status": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "readOnly": true
                },
                "health_checked_at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time",
                  "readOnly": true
                },
                "roles": {
                  "type": "array",
                  "readOnly": true,
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "color": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "name",
                      "color"
                    ]
                  }
                }
              },
              "required": [
                "id",
                "name",
                "type",
                "health_status",
                "health_checked_at",
                "roles"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "groups_loaded": {
          "type": "boolean",
          "readOnly": true
        },
        "available_servers": {
          "type": "array",
          "readOnly": true,
          "description": "WhatsApp groups returned by the authenticated QR session. Pass one of these IDs to the completion endpoint.",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "const": "group"
              }
            },
            "required": [
              "id",
              "name",
              "type"
            ]
          }
        }
      },
      "required": [
        "platform",
        "status"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "platform": "telegram",
    "status": "pending",
    "expires_at": "2026-09-01T12:10:00Z",
    "server": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/community-connections/{platform}/complete

Complete a community connection

Complete an authenticated WhatsApp QR connection by selecting a group returned by the status operation. The encrypted status token binds the session to the authenticated store and initiating user, and the server ID is revalidated against the provider response. Requires the `community` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.communityConnections.complete({
  "platform": "whatsapp",
  "statusToken": "replace-with-token-from-connection-start",
  "serverId": "replace-with-returned-server-id"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.community_connections.complete(
    platform="whatsapp",
    status_token="replace-with-token-from-connection-start",
    server_id="replace-with-returned-server-id"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->communityConnections()->complete(
    platform: 'whatsapp',
    statusToken: 'replace-with-token-from-connection-start',
    serverId: 'replace-with-returned-server-id',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CommunityConnectionsCompleteParams{}
    if err := json.Unmarshal([]byte("{\"status_token\":\"replace-with-token-from-connection-start\",\"server_id\":\"replace-with-returned-server-id\"}"), params); err != nil { panic(err) }
    result, err := client.CommunityConnections().Complete(context.Background(), "whatsapp", params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CommunityConnections.CompleteAsync(
    "whatsapp",
    new CommunityConnectionsCompleteOptions
    {
        StatusToken = "replace-with-token-from-connection-start",
        ServerId = "replace-with-returned-server-id",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.communityConnections.complete(platform = "whatsapp", statusToken = "replace-with-token-from-connection-start", serverId = "replace-with-returned-server-id")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.community_connections.complete(
  platform: "whatsapp",
  status_token: "replace-with-token-from-connection-start",
  server_id: "replace-with-returned-server-id"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::community_connections::CompleteParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CompleteParams::new(serde_json::from_str("{\"status_token\":\"replace-with-token-from-connection-start\",\"server_id\":\"replace-with-returned-server-id\"}")?);
    let result = client.community_connections().complete("whatsapp", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CommunityConnections.complete(client, "whatsapp", %{"status_token" => "replace-with-token-from-connection-start", "server_id" => "replace-with-returned-server-id"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp community-connections complete whatsapp --status-token replace-with-token-from-connection-start --server-id replace-with-returned-server-id --yes

```

- Method: `POST`

- Path: `/v2/community-connections/{platform}/complete`

- Full URL: `https://sell.app/api/v2/community-connections/{platform}/complete`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `community:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PLATFORM_ID='whatsapp'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/community-connections/${SELLAPP_PLATFORM_ID}/complete" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "status_token": "replace-with-token-from-connection-start",
  "server_id": "replace-with-returned-server-id"
}'
```

## Path Parameters
- `platform` (`string`, required): The community platform.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "status_token": {
      "type": "string",
      "maxLength": 4096,
      "x-sensitive": true
    },
    "server_id": {
      "type": "string",
      "maxLength": 255
    }
  },
  "required": [
    "status_token",
    "server_id"
  ]
}
```

Example (minimal):

```json
{
  "status_token": "replace-with-token-from-connection-start",
  "server_id": "replace-with-returned-server-id"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "platform": {
          "type": "string",
          "const": "whatsapp"
        },
        "connected": {
          "type": "boolean",
          "const": true
        },
        "server": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "name": {
              "type": "string"
            },
            "type": {
              "type": [
                "string",
                "null"
              ]
            },
            "health_status": {
              "type": [
                "string",
                "null"
              ],
              "readOnly": true
            },
            "health_checked_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "readOnly": true
            },
            "roles": {
              "type": "array",
              "readOnly": true,
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "color": {
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "name",
                  "color"
                ]
              }
            }
          },
          "required": [
            "id",
            "name",
            "type",
            "health_status",
            "health_checked_at",
            "roles"
          ]
        }
      },
      "required": [
        "platform",
        "connected",
        "server"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "platform": "whatsapp",
    "connected": true,
    "server": {
      "id": "string",
      "name": "string",
      "type": "string",
      "health_status": "string",
      "health_checked_at": "2019-08-24T14:15:22Z",
      "roles": [
        {
          "id": "string",
          "name": "string",
          "color": "string"
        }
      ]
    }
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/community-connections/{platform}/verify

Verify a community connection

Recheck provider and server health, then safely requeue eligible failed community grants. Requires the `community` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.communityConnections.verify({
  "platform": "discord"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.community_connections.verify(platform="discord")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->communityConnections()->verify(platform: 'discord');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.CommunityConnections().Verify(context.Background(), "discord")
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CommunityConnections.VerifyAsync("discord");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.communityConnections.verify(platform = "discord")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.community_connections.verify(platform: "discord")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::community_connections::VerifyParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = VerifyParams::default();
    let result = client.community_connections().verify("discord", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CommunityConnections.verify(client, "discord")
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp community-connections verify discord --yes

```

- Method: `POST`

- Path: `/v2/community-connections/{platform}/verify`

- Full URL: `https://sell.app/api/v2/community-connections/{platform}/verify`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `community:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PLATFORM_ID='discord'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/community-connections/${SELLAPP_PLATFORM_ID}/verify" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `platform` (`string`, required): The community platform.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "platform": {
          "type": "string",
          "enum": [
            "discord",
            "telegram",
            "slack",
            "whatsapp"
          ]
        },
        "healthy_count": {
          "type": "integer",
          "minimum": 0
        },
        "issue_count": {
          "type": "integer",
          "minimum": 0
        },
        "retried_count": {
          "type": "integer",
          "minimum": 0
        },
        "skipped_count": {
          "type": "integer",
          "minimum": 0
        },
        "skipped_products": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "unchanged_products": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "platform",
        "healthy_count",
        "issue_count",
        "retried_count",
        "skipped_count",
        "skipped_products",
        "unchanged_products"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "platform": "discord",
    "healthy_count": 0,
    "issue_count": 0,
    "retried_count": 0,
    "skipped_count": 0,
    "skipped_products": [],
    "unchanged_products": []
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## DELETE /v2/community-connections/{platform}

Disconnect a community platform

Idempotently disconnect the selected platform for the authenticated store and remove only that store's associated servers, channels, groups, or account links. Requires the `community` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.communityConnections.disconnect({
  "platform": "discord"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.community_connections.disconnect(platform="discord")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->communityConnections()->disconnect(platform: 'discord');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    if err := client.CommunityConnections().Disconnect(context.Background(), "discord"); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.CommunityConnections.DisconnectAsync("discord");
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.communityConnections.disconnect(platform = "discord")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.community_connections.disconnect(platform: "discord")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::community_connections::DisconnectParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = DisconnectParams::default();
    let result = client.community_connections().disconnect("discord", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CommunityConnections.disconnect(client, "discord")
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp community-connections disconnect discord --yes

```

- Method: `DELETE`

- Path: `/v2/community-connections/{platform}`

- Full URL: `https://sell.app/api/v2/community-connections/{platform}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `community:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PLATFORM_ID='discord'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v2/community-connections/${SELLAPP_PLATFORM_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `platform` (`string`, required): The community platform.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "platform": {
          "type": "string",
          "enum": [
            "discord",
            "telegram",
            "slack",
            "whatsapp"
          ]
        },
        "disconnected": {
          "type": "boolean",
          "const": true
        }
      },
      "required": [
        "platform",
        "disconnected"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "platform": "discord",
    "disconnected": true
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Legacy v1 (/docs/api/legacy-v1)

The API reference contains active v1 and v2 operations. A `/v1` path is not
deprecated unless the operation is marked `deprecated: true` in OpenAPI.

## Retired operations [#retired-operations]

The v1 listing operations return `410 Gone`. Use the corresponding v2 product
operation:

```text
/v1/listings                         → /v2/products
/v1/listings/search                  → /v2/products/search
/v1/listings/batch                   → /v2/products/batch
/v1/listings/{listing}               → /v2/products/{product}
```

The v1 invoice operations also return `410 Gone`. Replace the `/v1/invoices`
prefix with `/v2/invoices`; checkout, issue-replacement, mark-completed, and
mark-voided operations have direct v2 counterparts.

Each retired OpenAPI operation includes `deprecated: true` and an
`x-sellapp-replacement` method/path value for automated migration tooling.

## Active v1 resources [#active-v1-resources]

Coupons, sections, tickets, feedback, and blacklists currently retain active v1
operations. Continue using their documented paths until a replacement is
announced in the [API changelog](/api/api-changelog).

## Additional endpoint reference [#additional-endpoint-reference]

## GET /v1/blacklists

List all blacklist rules

Retrieve a paginated list of blacklist rules for your store. By default, a maximum of fifteen blacklist rules are returned per page.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.blacklists.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.blacklists.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->blacklists()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.BlacklistsListParams{}
    page := client.Blacklists().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Blacklists.ListAsync(new BlacklistsListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.blacklists.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.blacklists.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::blacklists::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.blacklists().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Blacklists.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp blacklists list

```

- Method: `GET`

- Path: `/v1/blacklists`

- Full URL: `https://sell.app/api/v1/blacklists`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/blacklists" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

A paginated list of blacklist rules.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data",
    "links",
    "meta"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "description": "A blacklist rule that blocks purchases matching the provided details.",
        "required": [
          "id",
          "type",
          "data",
          "description",
          "created_at",
          "updated_at",
          "store_id"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "description": "Unique identifier for the blacklist rule.",
            "example": 1
          },
          "type": {
            "type": "string",
            "description": "The type of blacklist rule.",
            "enum": [
              "ASN",
              "COUNTRY",
              "EMAIL",
              "IP",
              "WILDCARD_EMAIL"
            ]
          },
          "data": {
            "type": "string",
            "description": "The data associated with the rule type, such as an IP address, email, or country code.",
            "example": "leo.martin@example.com"
          },
          "description": {
            "type": "string",
            "description": "Why this blacklist rule exists.",
            "example": "Block the address used by our launch-day load-test bot."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the blacklist rule was created.",
            "example": "2022-12-12T12:12:12.000000Z"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the blacklist rule was last updated.",
            "example": "2022-12-12T12:12:12.000000Z"
          },
          "store_id": {
            "type": "integer",
            "description": "The store ID this blacklist rule belongs to.",
            "example": 1
          }
        }
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  },
  "example": {
    "data": [
      {
        "id": 1,
        "type": "EMAIL",
        "data": "leo.martin@example.com",
        "description": "Block the address used by our launch-day load-test bot.",
        "created_at": "2022-12-12T12:12:12.000000Z",
        "updated_at": "2022-12-12T12:12:12.000000Z",
        "store_id": 1
      }
    ],
    "links": {
      "first": "https://sell.app/api/v1/blacklists?page=1",
      "last": "https://sell.app/api/v1/blacklists?page=4",
      "prev": null,
      "next": "https://sell.app/api/v1/blacklists?page=2"
    },
    "meta": {
      "current_page": 1,
      "from": 1,
      "last_page": 4,
      "path": "https://sell.app/api/v1/blacklists",
      "per_page": 15,
      "to": 15,
      "total": 57
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "type": "EMAIL",
      "data": "leo.martin@example.com",
      "description": "Block the address used by our launch-day load-test bot.",
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1
    }
  ],
  "links": {
    "first": "https://sell.app/api/v1/blacklists?page=1",
    "last": "https://sell.app/api/v1/blacklists?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v1/blacklists",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v1/blacklists?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/blacklists

Create a blacklist rule

Create a new blacklist rule for your store.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.blacklists.create({
  "type": "ASN",
  "data": "@blocked.example",
  "description": "Retired after the growth experiment ended."
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.blacklists.create(
    type="ASN",
    data="@blocked.example",
    description="Retired after the growth experiment ended."
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->blacklists()->create(
    type: 'ASN',
    data: '@blocked.example',
    description: 'Retired after the growth experiment ended.',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.BlacklistsCreateParams{}
    if err := json.Unmarshal([]byte("{\"type\":\"ASN\",\"data\":\"@blocked.example\",\"description\":\"Retired after the growth experiment ended.\"}"), params); err != nil { panic(err) }
    result, err := client.Blacklists().Create(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Blacklists.CreateAsync(new BlacklistsCreateOptions
    {
        Type = JsonConvert.DeserializeObject<BlacklistType>("\"ASN\"")!,
        Data = "@blocked.example",
        Description = "Retired after the growth experiment ended.",
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.blacklists.create(type = app.sell.sellapp.types.BlacklistType("ASN"), data = "@blocked.example", description = "Retired after the growth experiment ended.")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.blacklists.create(
  type: "ASN",
  data: "@blocked.example",
  description: "Retired after the growth experiment ended."
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::blacklists::CreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateParams::new(serde_json::from_str("{\"type\":\"ASN\",\"data\":\"@blocked.example\",\"description\":\"Retired after the growth experiment ended.\"}")?);
    let result = client.blacklists().create(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Blacklists.create(client, %{"type" => "ASN", "data" => "@blocked.example", "description" => "Retired after the growth experiment ended."})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp blacklists create --type ASN --data test_data --description test_description --yes

```

- Method: `POST`

- Path: `/v1/blacklists`

- Full URL: `https://sell.app/api/v1/blacklists`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/blacklists" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "type": "WILDCARD_EMAIL",
  "data": "@blocked.example",
  "description": "Retired after the growth experiment ended."
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "data",
    "description"
  ],
  "properties": {
    "type": {
      "type": "string",
      "description": "The type of blacklist rule.",
      "enum": [
        "ASN",
        "COUNTRY",
        "EMAIL",
        "IP",
        "WILDCARD_EMAIL"
      ]
    },
    "data": {
      "type": "string",
      "description": "The value to blacklist.",
      "example": "@blocked.example"
    },
    "description": {
      "type": "string",
      "description": "Why this rule is being created.",
      "example": "Retired after the growth experiment ended."
    }
  },
  "example": {
    "type": "WILDCARD_EMAIL",
    "data": "@blocked.example",
    "description": "Retired after the growth experiment ended."
  }
}
```

Example:

```json
{
  "type": "WILDCARD_EMAIL",
  "data": "@blocked.example",
  "description": "Retired after the growth experiment ended."
}
```

## Responses

### 201

The newly created blacklist rule.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A blacklist rule that blocks purchases matching the provided details.",
      "required": [
        "id",
        "type",
        "data",
        "description",
        "created_at",
        "updated_at",
        "store_id"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "description": "Unique identifier for the blacklist rule.",
          "example": 1
        },
        "type": {
          "type": "string",
          "description": "The type of blacklist rule.",
          "enum": [
            "ASN",
            "COUNTRY",
            "EMAIL",
            "IP",
            "WILDCARD_EMAIL"
          ]
        },
        "data": {
          "type": "string",
          "description": "The data associated with the rule type, such as an IP address, email, or country code.",
          "example": "leo.martin@example.com"
        },
        "description": {
          "type": "string",
          "description": "Why this blacklist rule exists.",
          "example": "Block the address used by our launch-day load-test bot."
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was created.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was last updated.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "store_id": {
          "type": "integer",
          "description": "The store ID this blacklist rule belongs to.",
          "example": 1
        }
      }
    }
  },
  "example": {
    "data": {
      "id": 1,
      "type": "WILDCARD_EMAIL",
      "data": "@blocked.example",
      "description": "Retired after the growth experiment ended.",
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "type": "WILDCARD_EMAIL",
    "data": "@blocked.example",
    "description": "Retired after the growth experiment ended.",
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/blacklists/{blacklist}

Retrieve a blacklist rule

Retrieve a specific blacklist rule by its unique identifier.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.blacklists.get({
  "blacklist": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.blacklists.get(blacklist=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->blacklists()->get(blacklist: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Blacklists().Get(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Blacklists.GetAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.blacklists.get(blacklist = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.blacklists.get(blacklist: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let result = client.blacklists().get("1").await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Blacklists.get(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp blacklists get 1

```

- Method: `GET`

- Path: `/v1/blacklists/{blacklist}`

- Full URL: `https://sell.app/api/v1/blacklists/{blacklist}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_BLACKLIST_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/blacklists/${SELLAPP_BLACKLIST_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `blacklist` (`integer`, required): The unique identifier of the blacklist rule.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

The requested blacklist rule.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A blacklist rule that blocks purchases matching the provided details.",
      "required": [
        "id",
        "type",
        "data",
        "description",
        "created_at",
        "updated_at",
        "store_id"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "description": "Unique identifier for the blacklist rule.",
          "example": 1
        },
        "type": {
          "type": "string",
          "description": "The type of blacklist rule.",
          "enum": [
            "ASN",
            "COUNTRY",
            "EMAIL",
            "IP",
            "WILDCARD_EMAIL"
          ]
        },
        "data": {
          "type": "string",
          "description": "The data associated with the rule type, such as an IP address, email, or country code.",
          "example": "leo.martin@example.com"
        },
        "description": {
          "type": "string",
          "description": "Why this blacklist rule exists.",
          "example": "Block the address used by our launch-day load-test bot."
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was created.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was last updated.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "store_id": {
          "type": "integer",
          "description": "The store ID this blacklist rule belongs to.",
          "example": 1
        }
      }
    }
  },
  "example": {
    "data": {
      "id": 1,
      "type": "WILDCARD_EMAIL",
      "data": "@blocked.example",
      "description": "Retired after the growth experiment ended.",
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "type": "WILDCARD_EMAIL",
    "data": "@blocked.example",
    "description": "Retired after the growth experiment ended.",
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v1/blacklists/{blacklist}

Update a blacklist rule

Update one or more attributes on an existing blacklist rule.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.blacklists.update({
  "blacklist": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.blacklists.update(blacklist=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->blacklists()->update(blacklist: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.BlacklistsUpdateParams{}
    if err := json.Unmarshal([]byte("{}"), params); err != nil { panic(err) }
    result, err := client.Blacklists().Update(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Blacklists.UpdateAsync(
    "1",
    new BlacklistsUpdateOptions
    {
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.blacklists.update(blacklist = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.blacklists.update(blacklist: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::blacklists::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{}")?);
    let result = client.blacklists().update("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Blacklists.update(client, 1, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp blacklists update 1 --yes

```

- Method: `PATCH`

- Path: `/v1/blacklists/{blacklist}`

- Full URL: `https://sell.app/api/v1/blacklists/{blacklist}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_BLACKLIST_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v1/blacklists/${SELLAPP_BLACKLIST_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "type": "WILDCARD_EMAIL",
  "data": "@blocked-domain.example",
  "description": "Block purchases from this email domain."
}'
```

## Path Parameters
- `blacklist` (`integer`, required): The unique identifier of the blacklist rule.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "description": "Provide one or more fields to update an existing blacklist rule.",
  "properties": {
    "type": {
      "type": "string",
      "description": "The type of blacklist rule.",
      "enum": [
        "ASN",
        "COUNTRY",
        "EMAIL",
        "IP",
        "WILDCARD_EMAIL"
      ]
    },
    "data": {
      "type": "string",
      "description": "The updated value to blacklist.",
      "example": "@blocked-domain.example"
    },
    "description": {
      "type": "string",
      "description": "The updated reason for this rule.",
      "example": "Block purchases from this email domain."
    }
  },
  "example": {
    "type": "WILDCARD_EMAIL",
    "data": "@blocked-domain.example",
    "description": "Block purchases from this email domain."
  }
}
```

Example:

```json
{
  "type": "WILDCARD_EMAIL",
  "data": "@blocked-domain.example",
  "description": "Block purchases from this email domain."
}
```

## Responses

### 200

The updated blacklist rule.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A blacklist rule that blocks purchases matching the provided details.",
      "required": [
        "id",
        "type",
        "data",
        "description",
        "created_at",
        "updated_at",
        "store_id"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "description": "Unique identifier for the blacklist rule.",
          "example": 1
        },
        "type": {
          "type": "string",
          "description": "The type of blacklist rule.",
          "enum": [
            "ASN",
            "COUNTRY",
            "EMAIL",
            "IP",
            "WILDCARD_EMAIL"
          ]
        },
        "data": {
          "type": "string",
          "description": "The data associated with the rule type, such as an IP address, email, or country code.",
          "example": "leo.martin@example.com"
        },
        "description": {
          "type": "string",
          "description": "Why this blacklist rule exists.",
          "example": "Block the address used by our launch-day load-test bot."
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was created.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was last updated.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "store_id": {
          "type": "integer",
          "description": "The store ID this blacklist rule belongs to.",
          "example": 1
        }
      }
    }
  },
  "example": {
    "data": {
      "id": 1,
      "type": "WILDCARD_EMAIL",
      "data": "@blocked.example",
      "description": "Retired after the growth experiment ended.",
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "type": "WILDCARD_EMAIL",
    "data": "@blocked-domain.example",
    "description": "Block purchases from this email domain.",
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## DELETE /v1/blacklists/{blacklist}

Delete a blacklist rule

Permanently delete a blacklist rule from your store.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.blacklists.delete({
  "blacklist": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.blacklists.delete(blacklist=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->blacklists()->delete(blacklist: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    if err := client.Blacklists().Delete(context.Background(), 1); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.Blacklists.DeleteAsync("1");
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.blacklists.delete(blacklist = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.blacklists.delete(blacklist: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let result = client.blacklists().delete("1").await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Blacklists.delete(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp blacklists delete 1 --yes

```

- Method: `DELETE`

- Path: `/v1/blacklists/{blacklist}`

- Full URL: `https://sell.app/api/v1/blacklists/{blacklist}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_BLACKLIST_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v1/blacklists/${SELLAPP_BLACKLIST_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `blacklist` (`integer`, required): The unique identifier of the blacklist rule.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

The blacklist rule was deleted successfully.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A blacklist rule that blocks purchases matching the provided details.",
      "required": [
        "id",
        "type",
        "data",
        "description",
        "created_at",
        "updated_at",
        "store_id"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "description": "Unique identifier for the blacklist rule.",
          "example": 1
        },
        "type": {
          "type": "string",
          "description": "The type of blacklist rule.",
          "enum": [
            "ASN",
            "COUNTRY",
            "EMAIL",
            "IP",
            "WILDCARD_EMAIL"
          ]
        },
        "data": {
          "type": "string",
          "description": "The data associated with the rule type, such as an IP address, email, or country code.",
          "example": "leo.martin@example.com"
        },
        "description": {
          "type": "string",
          "description": "Why this blacklist rule exists.",
          "example": "Block the address used by our launch-day load-test bot."
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was created.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was last updated.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "store_id": {
          "type": "integer",
          "description": "The store ID this blacklist rule belongs to.",
          "example": 1
        }
      }
    }
  },
  "example": {
    "data": {
      "id": 1,
      "type": "WILDCARD_EMAIL",
      "data": "@blocked.example",
      "description": "Retired after the growth experiment ended.",
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "type": "WILDCARD_EMAIL",
    "data": "@blocked.example",
    "description": "Retired after the growth experiment ended.",
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/coupons

List all coupons

List your store's coupons, 15 per page by default.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsListParams{}
    page := client.Coupons().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.ListAsync(new CouponsListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.coupons().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons list

```

- Method: `GET`

- Path: `/v1/coupons`

- Full URL: `https://sell.app/api/v1/coupons`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/coupons" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": "string"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "store_wide": {
            "type": "boolean"
          },
          "minimum_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
            "example": "2026-07-03 12:15:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "maximum_discount_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
          },
          "products": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "discount",
          "limit",
          "store_wide",
          "minimum_amount",
          "expires_at",
          "created_at",
          "updated_at",
          "store_id",
          "deleted_at",
          "maximum_discount_amount",
          "products",
          "product_variants"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "code": "BONANZA",
      "type": "PERCENTAGE",
      "discount": "80",
      "limit": null,
      "store_wide": true,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "deleted_at": null,
      "products": [],
      "product_variants": [],
      "maximum_discount_amount": null
    }
  ],
  "links": {
    "first": "https://sell.app/api/v1/coupons?page=1",
    "last": "https://sell.app/api/v1/coupons?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v1/coupons",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v1/coupons?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/coupons

Create a coupon

Create a discount code for your store.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.create({
  "code": "PLAN10",
  "type": "PERCENTAGE",
  "discount": 10,
  "storeWide": false,
  "products": [123, 456],
  "productVariants": [1001, 1002]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.create(
    code="PLAN10",
    type="PERCENTAGE",
    discount=10,
    store_wide=False,
    products=[123, 456],
    product_variants=[1001, 1002]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->create(
    code: 'PLAN10',
    type: 'PERCENTAGE',
    discount: 10,
    storeWide: false,
    products: [123, 456],
    productVariants: [1001, 1002],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsCreateParams{}
    if err := json.Unmarshal([]byte("{\"code\":\"PLAN10\",\"type\":\"PERCENTAGE\",\"discount\":10,\"store_wide\":false,\"products\":[123,456],\"product_variants\":[1001,1002]}"), params); err != nil { panic(err) }
    result, err := client.Coupons().Create(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.CreateAsync(new CouponsCreateOptions
    {
        Code = "PLAN10",
        Type = JsonConvert.DeserializeObject<SdkCreateCouponRequestApplicationJsonType>("\"PERCENTAGE\"")!,
        Discount = JsonConvert.DeserializeObject<OneOf.OneOf<double, string>>("10")!,
        StoreWide = false,
        Products = JsonConvert.DeserializeObject<List<long>>("[123,456]")!,
        ProductVariants = JsonConvert.DeserializeObject<List<long>>("[1001,1002]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.create(code = "PLAN10", type = app.sell.sellapp.types.SdkCreateCouponRequestApplicationJsonType("PERCENTAGE"), discount = 10, storeWide = false, products = listOf(123L, 456L), productVariants = listOf(1001L, 1002L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.create(
  code: "PLAN10",
  type: "PERCENTAGE",
  discount: 10,
  store_wide: false,
  products: [123, 456],
  product_variants: [1001, 1002]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::CreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateParams::new(serde_json::from_str("{\"code\":\"PLAN10\",\"type\":\"PERCENTAGE\",\"discount\":10,\"store_wide\":false,\"products\":[123,456],\"product_variants\":[1001,1002]}")?);
    let result = client.coupons().create(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.create(client, %{"code" => "PLAN10", "type" => "PERCENTAGE", "discount" => 10, "store_wide" => false, "products" => [123, 456], "product_variants" => [1001, 1002]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons create --body '{"code":"PLAN10","type":"PERCENTAGE","discount":10,"store_wide":false,"products":[123,456],"product_variants":[1001,1002]}' --yes

```

- Method: `POST`

- Path: `/v1/coupons`

- Full URL: `https://sell.app/api/v1/coupons`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/coupons" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "code": "PLAN10",
  "type": "PERCENTAGE",
  "discount": 10,
  "store_wide": false,
  "products": [
    123,
    456
  ],
  "product_variants": [
    1001,
    1002
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "code": {
      "type": "string",
      "maxLength": 255
    },
    "type": {
      "type": "string",
      "enum": [
        "PERCENTAGE",
        "AMOUNT"
      ]
    },
    "discount": {
      "type": [
        "number",
        "string"
      ],
      "minimum": 1,
      "maxLength": 255,
      "description": "A decimal discount value of at least 1. Percentage discounts cannot exceed 100; amount discounts use the store currency's major unit."
    },
    "store_wide": {
      "type": "boolean"
    },
    "products": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "integer"
      },
      "description": "Product IDs the coupon applies to when store_wide is false."
    },
    "product_variants": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "description": "Optional variant restrictions. Every variant must belong to a selected product. Products without listed variants remain eligible on all variants."
    },
    "limit": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "expires_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "A future date and time, or null for no expiry."
    },
    "minimum_amount": {
      "type": [
        "number",
        "string",
        "null"
      ],
      "minimum": 1,
      "maxLength": 255,
      "description": "A decimal minimum order amount in the store currency's major unit, or null for no minimum."
    }
  },
  "required": [
    "code",
    "type",
    "discount",
    "store_wide"
  ]
}
```

Example:

```json
{
  "code": "PLAN10",
  "type": "PERCENTAGE",
  "discount": 10,
  "store_wide": false,
  "products": [
    123,
    456
  ],
  "product_variants": [
    1001,
    1002
  ]
}
```

## Responses

### 201

Coupon created successfully.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "code": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "enum": [
            "PERCENTAGE",
            "AMOUNT"
          ]
        },
        "discount": {
          "type": "string"
        },
        "limit": {
          "type": [
            "integer",
            "null"
          ]
        },
        "store_wide": {
          "type": "boolean"
        },
        "minimum_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
          "example": "2026-07-03 12:15:00"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "maximum_discount_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
        },
        "products": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
        },
        "product_variants": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
        }
      },
      "required": [
        "id",
        "code",
        "type",
        "discount",
        "limit",
        "store_wide",
        "minimum_amount",
        "expires_at",
        "created_at",
        "updated_at",
        "store_id",
        "deleted_at",
        "maximum_discount_amount",
        "products",
        "product_variants"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "code": "PLAN10",
    "type": "PERCENTAGE",
    "discount": "10",
    "limit": null,
    "store_wide": false,
    "minimum_amount": null,
    "expires_at": null,
    "created_at": "2026-08-30T12:00:01.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "store_id": 1,
    "deleted_at": null,
    "products": [
      123,
      456
    ],
    "product_variants": [
      1001,
      1002
    ],
    "maximum_discount_amount": null
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/coupons/{coupon}

Retrieve a coupon

Retrieve a coupon by its ID.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.get({
  "coupon": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.get(coupon=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->get(coupon: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsGetParams{}
    result, err := client.Coupons().Get(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.GetAsync(
    "1",
    new CouponsGetOptions
    {
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.get(coupon = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.get(coupon: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.coupons().get("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.get(client, 1, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons get 1

```

- Method: `GET`

- Path: `/v1/coupons/{coupon}`

- Full URL: `https://sell.app/api/v1/coupons/{coupon}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COUPON_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/coupons/${SELLAPP_COUPON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `coupon` (`integer`, required): The coupon path parameter.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "code": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "enum": [
            "PERCENTAGE",
            "AMOUNT"
          ]
        },
        "discount": {
          "type": "string"
        },
        "limit": {
          "type": [
            "integer",
            "null"
          ]
        },
        "store_wide": {
          "type": "boolean"
        },
        "minimum_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
          "example": "2026-07-03 12:15:00"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "maximum_discount_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
        },
        "products": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
        },
        "product_variants": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
        }
      },
      "required": [
        "id",
        "code",
        "type",
        "discount",
        "limit",
        "store_wide",
        "minimum_amount",
        "expires_at",
        "created_at",
        "updated_at",
        "store_id",
        "deleted_at",
        "maximum_discount_amount",
        "products",
        "product_variants"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "code": "BONANZA",
    "type": "PERCENTAGE",
    "discount": "80",
    "limit": null,
    "store_wide": true,
    "minimum_amount": null,
    "expires_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "deleted_at": null,
    "products": [],
    "product_variants": [],
    "maximum_discount_amount": null
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v1/coupons/{coupon}

Update a coupon

Change a coupon's discount, limits, or eligible products.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.update({
  "coupon": 1,
  "storeWide": false,
  "products": [123],
  "productVariants": [1001, 1002]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.update(
    coupon=1,
    store_wide=False,
    products=[123],
    product_variants=[1001, 1002]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->update(
    coupon: 1,
    storeWide: false,
    products: [123],
    productVariants: [1001, 1002],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsUpdateParams{}
    if err := json.Unmarshal([]byte("{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}"), params); err != nil { panic(err) }
    result, err := client.Coupons().Update(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.UpdateAsync(
    "1",
    new CouponsUpdateOptions
    {
        StoreWide = false,
        Products = JsonConvert.DeserializeObject<List<long>>("[123]")!,
        ProductVariants = JsonConvert.DeserializeObject<List<long>>("[1001,1002]")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.update(coupon = "1", storeWide = app.sell.sellapp.common.http.PatchField.Present(false), products = app.sell.sellapp.common.http.PatchField.Present(listOf(123L)), productVariants = app.sell.sellapp.common.http.PatchField.Present(listOf(1001L, 1002L)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.update(
  coupon: 1,
  store_wide: false,
  products: [123],
  product_variants: [1001, 1002]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}")?);
    let result = client.coupons().update("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.update(client, 1, %{"store_wide" => false, "products" => [123], "product_variants" => [1001, 1002]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons update 1 --body '{"store_wide":false,"products":[123],"product_variants":[1001,1002]}' --yes

```

- Method: `PATCH`

- Path: `/v1/coupons/{coupon}`

- Full URL: `https://sell.app/api/v1/coupons/{coupon}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COUPON_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v1/coupons/${SELLAPP_COUPON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "store_wide": false,
  "products": [
    123
  ],
  "product_variants": [
    1001,
    1002
  ]
}'
```

## Path Parameters
- `coupon` (`integer`, required): The coupon path parameter.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "code": {
      "type": "string",
      "maxLength": 255
    },
    "type": {
      "type": "string",
      "enum": [
        "PERCENTAGE",
        "AMOUNT"
      ]
    },
    "discount": {
      "type": [
        "number",
        "string"
      ],
      "minimum": 1,
      "maxLength": 255,
      "description": "A decimal discount value of at least 1. Percentage discounts cannot exceed 100; amount discounts use the store currency's major unit."
    },
    "store_wide": {
      "type": "boolean"
    },
    "products": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "integer"
      },
      "description": "Product IDs the coupon applies to when store_wide is false."
    },
    "product_variants": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "description": "Optional variant restrictions. Omit to preserve existing restrictions or send an empty array to allow every variant of the selected products."
    },
    "limit": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "expires_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "A future date and time, or null for no expiry."
    },
    "minimum_amount": {
      "type": [
        "number",
        "string",
        "null"
      ],
      "minimum": 1,
      "maxLength": 255,
      "description": "A decimal minimum order amount in the store currency's major unit, or null for no minimum."
    }
  }
}
```

Example:

```json
{
  "store_wide": false,
  "products": [
    123
  ],
  "product_variants": [
    1001,
    1002
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "code": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "enum": [
            "PERCENTAGE",
            "AMOUNT"
          ]
        },
        "discount": {
          "type": "string"
        },
        "limit": {
          "type": [
            "integer",
            "null"
          ]
        },
        "store_wide": {
          "type": "boolean"
        },
        "minimum_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
          "example": "2026-07-03 12:15:00"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "maximum_discount_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
        },
        "products": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
        },
        "product_variants": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
        }
      },
      "required": [
        "id",
        "code",
        "type",
        "discount",
        "limit",
        "store_wide",
        "minimum_amount",
        "expires_at",
        "created_at",
        "updated_at",
        "store_id",
        "deleted_at",
        "maximum_discount_amount",
        "products",
        "product_variants"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "code": "BAZINGA",
    "type": "PERCENTAGE",
    "discount": "80",
    "limit": null,
    "store_wide": false,
    "minimum_amount": null,
    "expires_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "store_id": 1,
    "deleted_at": null,
    "products": [
      123
    ],
    "product_variants": [
      1001,
      1002
    ],
    "maximum_discount_amount": null
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## DELETE /v1/coupons/{coupon}

Delete a coupon

Soft-delete a coupon. The returned coupon includes its deleted_at timestamp; use with_trashed or only_trashed to retrieve soft-deleted coupons later.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.delete({
  "coupon": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.delete(coupon=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->delete(coupon: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsDeleteParams{}
    if err := client.Coupons().Delete(context.Background(), 1, params); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.Coupons.DeleteAsync(
    "1",
    new CouponsDeleteOptions
    {
    }
);
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.delete(coupon = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.delete(coupon: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::DeleteParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = DeleteParams::default();
    let result = client.coupons().delete("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.delete(client, 1, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons delete 1 --yes

```

- Method: `DELETE`

- Path: `/v1/coupons/{coupon}`

- Full URL: `https://sell.app/api/v1/coupons/{coupon}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COUPON_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v1/coupons/${SELLAPP_COUPON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `coupon` (`integer`, required): The coupon path parameter.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "code": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "enum": [
            "PERCENTAGE",
            "AMOUNT"
          ]
        },
        "discount": {
          "type": "string"
        },
        "limit": {
          "type": [
            "integer",
            "null"
          ]
        },
        "store_wide": {
          "type": "boolean"
        },
        "minimum_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
          "example": "2026-07-03 12:15:00"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "maximum_discount_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
        },
        "products": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
        },
        "product_variants": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
        }
      },
      "required": [
        "id",
        "code",
        "type",
        "discount",
        "limit",
        "store_wide",
        "minimum_amount",
        "expires_at",
        "created_at",
        "updated_at",
        "store_id",
        "deleted_at",
        "maximum_discount_amount",
        "products",
        "product_variants"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "code": "BONANZA",
    "type": "PERCENTAGE",
    "discount": "80",
    "limit": null,
    "store_wide": true,
    "minimum_amount": null,
    "expires_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "store_id": 1,
    "deleted_at": "2026-08-30T12:00:01.000000Z",
    "products": [],
    "product_variants": [],
    "maximum_discount_amount": null
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PUT /v1/coupons/{coupon}

Update a coupon

Change a coupon's discount, limits, or eligible products.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.replace({
  "coupon": 1,
  "storeWide": false,
  "products": [123],
  "productVariants": [1001, 1002]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.replace(
    coupon=1,
    store_wide=False,
    products=[123],
    product_variants=[1001, 1002]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->replace(
    coupon: 1,
    storeWide: false,
    products: [123],
    productVariants: [1001, 1002],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsReplaceParams{}
    if err := json.Unmarshal([]byte("{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}"), params); err != nil { panic(err) }
    result, err := client.Coupons().Replace(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.ReplaceAsync(
    "1",
    new CouponsReplaceOptions
    {
        StoreWide = false,
        Products = JsonConvert.DeserializeObject<List<long>>("[123]")!,
        ProductVariants = JsonConvert.DeserializeObject<List<long>>("[1001,1002]")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.replace(coupon = "1", storeWide = false, products = listOf(123L), productVariants = listOf(1001L, 1002L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.replace(
  coupon: 1,
  store_wide: false,
  products: [123],
  product_variants: [1001, 1002]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::ReplaceParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceParams::new(serde_json::from_str("{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}")?);
    let result = client.coupons().replace("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.replace(client, 1, %{"store_wide" => false, "products" => [123], "product_variants" => [1001, 1002]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons replace 1 --body '{"store_wide":false,"products":[123],"product_variants":[1001,1002]}' --yes

```

- Method: `PUT`

- Path: `/v1/coupons/{coupon}`

- Full URL: `https://sell.app/api/v1/coupons/{coupon}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COUPON_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v1/coupons/${SELLAPP_COUPON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "store_wide": false,
  "products": [
    123
  ],
  "product_variants": [
    1001,
    1002
  ]
}'
```

## Path Parameters
- `coupon` (`integer`, required): The coupon path parameter.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "code": {
      "type": "string",
      "maxLength": 255
    },
    "type": {
      "type": "string",
      "enum": [
        "PERCENTAGE",
        "AMOUNT"
      ]
    },
    "discount": {
      "type": [
        "number",
        "string"
      ],
      "minimum": 1,
      "maxLength": 255,
      "description": "A decimal discount value of at least 1. Percentage discounts cannot exceed 100; amount discounts use the store currency's major unit."
    },
    "store_wide": {
      "type": "boolean"
    },
    "products": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "integer"
      },
      "description": "Product IDs the coupon applies to when store_wide is false."
    },
    "product_variants": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "description": "Optional variant restrictions. Omit to preserve existing restrictions or send an empty array to allow every variant of the selected products."
    },
    "limit": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "expires_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "A future date and time, or null for no expiry."
    },
    "minimum_amount": {
      "type": [
        "number",
        "string",
        "null"
      ],
      "minimum": 1,
      "maxLength": 255,
      "description": "A decimal minimum order amount in the store currency's major unit, or null for no minimum."
    }
  }
}
```

Example:

```json
{
  "store_wide": false,
  "products": [
    123
  ],
  "product_variants": [
    1001,
    1002
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "code": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "enum": [
            "PERCENTAGE",
            "AMOUNT"
          ]
        },
        "discount": {
          "type": "string"
        },
        "limit": {
          "type": [
            "integer",
            "null"
          ]
        },
        "store_wide": {
          "type": "boolean"
        },
        "minimum_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
          "example": "2026-07-03 12:15:00"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "maximum_discount_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
        },
        "products": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
        },
        "product_variants": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
        }
      },
      "required": [
        "id",
        "code",
        "type",
        "discount",
        "limit",
        "store_wide",
        "minimum_amount",
        "expires_at",
        "created_at",
        "updated_at",
        "store_id",
        "deleted_at",
        "maximum_discount_amount",
        "products",
        "product_variants"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "code": "BAZINGA",
    "type": "PERCENTAGE",
    "discount": "80",
    "limit": null,
    "store_wide": false,
    "minimum_amount": null,
    "expires_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "store_id": 1,
    "deleted_at": null,
    "products": [
      123
    ],
    "product_variants": [
      1001,
      1002
    ],
    "maximum_discount_amount": null
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/feedback

List all feedback

List customer feedback for your store, 15 entries per page by default.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.feedback.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.feedback.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->feedback()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.FeedbackListParams{}
    page := client.Feedback().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Feedback.ListAsync(new FeedbackListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.feedback.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.feedback.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::feedback::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.feedback().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Feedback.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp feedback list

```

- Method: `GET`

- Path: `/v1/feedback`

- Full URL: `https://sell.app/api/v1/feedback`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/feedback" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "feedback": {
            "type": "string"
          },
          "rating": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "listing_id": {
            "type": "integer"
          },
          "invoice_id": {
            "type": "integer"
          },
          "store_id": {
            "type": "integer"
          },
          "metadata": {
            "anyOf": [
              {
                "type": "object",
                "description": "Import details recorded when the feedback came from another platform, or null when the customer left it in the store.",
                "properties": {
                  "imported_from": {
                    "type": "string"
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "message": {
            "type": "string"
          },
          "reply": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_automatic": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "feedback",
          "rating",
          "deleted_at",
          "created_at",
          "updated_at",
          "listing_id",
          "invoice_id",
          "store_id",
          "metadata",
          "message",
          "reply",
          "is_automatic"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "feedback": "POSITIVE",
      "rating": 5,
      "deleted_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "listing_id": 1,
      "invoice_id": 1,
      "store_id": 1,
      "metadata": null,
      "message": "The download arrived immediately and the setup instructions were clear.",
      "reply": "Thank you for your feedback.",
      "is_automatic": true
    }
  ],
  "links": {
    "first": "https://sell.app/api/v1/feedback?page=1",
    "last": "https://sell.app/api/v1/feedback?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v1/feedback",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v1/feedback?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/feedback/{feedback}

Retrieve specific feedback

Retrieve a customer's feedback by its ID.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.feedback.get({
  "feedback": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.feedback.get(feedback=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->feedback()->get(feedback: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Feedback().Get(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Feedback.GetAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.feedback.get(feedback = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.feedback.get(feedback: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let result = client.feedback().get("1").await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Feedback.get(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp feedback get 1

```

- Method: `GET`

- Path: `/v1/feedback/{feedback}`

- Full URL: `https://sell.app/api/v1/feedback/{feedback}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_FEEDBACK_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/feedback/${SELLAPP_FEEDBACK_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `feedback` (`integer`, required): The feedback path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "feedback": {
          "type": "string"
        },
        "rating": {
          "type": "integer"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "listing_id": {
          "type": "integer"
        },
        "invoice_id": {
          "type": "integer"
        },
        "store_id": {
          "type": "integer"
        },
        "metadata": {
          "anyOf": [
            {
              "type": "object",
              "description": "Import details recorded when the feedback came from another platform, or null when the customer left it in the store.",
              "properties": {
                "imported_from": {
                  "type": "string"
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "message": {
          "type": "string"
        },
        "reply": {
          "type": [
            "string",
            "null"
          ]
        },
        "is_automatic": {
          "type": "boolean"
        }
      },
      "required": [
        "id",
        "feedback",
        "rating",
        "deleted_at",
        "created_at",
        "updated_at",
        "listing_id",
        "invoice_id",
        "store_id",
        "metadata",
        "message",
        "reply",
        "is_automatic"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "feedback": "POSITIVE",
    "rating": 5,
    "deleted_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "listing_id": 1,
    "invoice_id": 1,
    "store_id": 1,
    "metadata": null,
    "message": "The download arrived immediately and the setup instructions were clear.",
    "reply": "Thank you for your feedback.",
    "is_automatic": true
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v1/feedback/{feedback}

Reply to feedback

Publish a seller reply to a customer's feedback.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.feedback.reply({
  "feedback": 1,
  "reply": "Please contact support if you need help with your download."
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.feedback.reply(
    feedback=1,
    reply="Please contact support if you need help with your download."
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->feedback()->reply(
    feedback: 1,
    reply: 'Please contact support if you need help with your download.',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.FeedbackReplyParams{}
    if err := json.Unmarshal([]byte("{\"reply\":\"Please contact support if you need help with your download.\"}"), params); err != nil { panic(err) }
    result, err := client.Feedback().Reply(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Feedback.ReplyAsync(
    "1",
    new FeedbackReplyOptions
    {
        Reply = "Please contact support if you need help with your download.",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.feedback.reply(feedback = "1", reply = "Please contact support if you need help with your download.")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.feedback.reply(
  feedback: 1,
  reply: "Please contact support if you need help with your download."
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::feedback::ReplyParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplyParams::new(serde_json::from_str("{\"reply\":\"Please contact support if you need help with your download.\"}")?);
    let result = client.feedback().reply("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Feedback.reply(client, 1, %{"reply" => "Please contact support if you need help with your download."})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp feedback reply 1 --reply 'Please contact support if you need help with your download.' --yes

```

- Method: `PATCH`

- Path: `/v1/feedback/{feedback}`

- Full URL: `https://sell.app/api/v1/feedback/{feedback}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_FEEDBACK_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v1/feedback/${SELLAPP_FEEDBACK_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "reply": "Please contact support if you need help with your download."
}'
```

## Path Parameters
- `feedback` (`integer`, required): The feedback path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "reply": {
      "type": "string"
    }
  },
  "required": [
    "reply"
  ]
}
```

Example:

```json
{
  "reply": "Please contact support if you need help with your download."
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "feedback": {
          "type": "string"
        },
        "rating": {
          "type": "integer"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "listing_id": {
          "type": "integer"
        },
        "invoice_id": {
          "type": "integer"
        },
        "store_id": {
          "type": "integer"
        },
        "metadata": {
          "anyOf": [
            {
              "type": "object",
              "description": "Import details recorded when the feedback came from another platform, or null when the customer left it in the store.",
              "properties": {
                "imported_from": {
                  "type": "string"
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "message": {
          "type": "string"
        },
        "reply": {
          "type": [
            "string",
            "null"
          ]
        },
        "is_automatic": {
          "type": "boolean"
        }
      },
      "required": [
        "id",
        "feedback",
        "rating",
        "deleted_at",
        "created_at",
        "updated_at",
        "listing_id",
        "invoice_id",
        "store_id",
        "metadata",
        "message",
        "reply",
        "is_automatic"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "feedback": "POSITIVE",
    "rating": 5,
    "deleted_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "listing_id": 1,
    "invoice_id": 1,
    "store_id": 1,
    "metadata": null,
    "message": "The download arrived immediately and the setup instructions were clear.",
    "reply": "Please contact support if you need help with your download.",
    "is_automatic": true
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/sections

List all sections

List your storefront sections, 15 per page by default.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.SectionsListParams{}
    page := client.Sections().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Sections.ListAsync(new SectionsListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::sections::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.sections().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections list

```

- Method: `GET`

- Path: `/v1/sections`

- Full URL: `https://sell.app/api/v1/sections`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/sections" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "hidden": {
            "type": "boolean"
          },
          "order": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "groups_linked": {
            "type": "integer"
          },
          "products_linked": {
            "type": "integer"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "title": {
                  "type": "string"
                },
                "group_products": {
                  "type": "integer"
                }
              },
              "required": [
                "id",
                "title",
                "group_products"
              ]
            }
          },
          "products": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The product identifier, returned as a string by the section resource."
                },
                "title": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "title",
                "description"
              ]
            }
          }
        },
        "required": [
          "id",
          "title",
          "slug",
          "hidden",
          "order",
          "created_at",
          "updated_at",
          "store_id",
          "groups_linked",
          "products_linked",
          "groups",
          "products"
        ]
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "title": "Dissection",
      "slug": "dissection",
      "hidden": false,
      "order": 1,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "groups_linked": 1,
      "products_linked": 1,
      "groups": [
        {
          "id": 1,
          "title": "Project Planning Toolkit",
          "group_products": 1
        }
      ],
      "products": [
        {
          "id": "1",
          "title": "Project Planning Guide",
          "description": "Includes practical examples and a downloadable checklist."
        }
      ]
    }
  ],
  "links": {
    "first": "https://sell.app/api/v1/sections?page=1",
    "last": "https://sell.app/api/v1/sections?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v1/sections",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v1/sections?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/sections

Create a section

Create a section to organize your storefront.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.create({
  "title": "Founder resources",
  "hidden": false
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.create(
    title="Founder resources",
    hidden=False
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->create(
    title: 'Founder resources',
    hidden: false,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.SectionsCreateParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Founder resources\",\"hidden\":false}"), params); err != nil { panic(err) }
    result, err := client.Sections().Create(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Sections.CreateAsync(new SectionsCreateOptions
    {
        Title = "Founder resources",
        Hidden = false,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.create(title = "Founder resources", hidden = false)
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.create(
  title: "Founder resources",
  hidden: false
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::sections::CreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateParams::new(serde_json::from_str("{\"title\":\"Founder resources\",\"hidden\":false}")?);
    let result = client.sections().create(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.create(client, %{"title" => "Founder resources", "hidden" => false})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections create --title 'Founder resources' --hidden false --yes

```

- Method: `POST`

- Path: `/v1/sections`

- Full URL: `https://sell.app/api/v1/sections`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/sections" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Founder resources",
  "hidden": false
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255
    },
    "hidden": {
      "type": "boolean"
    }
  },
  "required": [
    "title",
    "hidden"
  ]
}
```

Example:

```json
{
  "title": "Founder resources",
  "hidden": false
}
```

## Responses

### 201

The section was created successfully.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": [
            "string",
            "null"
          ]
        },
        "hidden": {
          "type": "boolean"
        },
        "order": {
          "type": "integer"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "groups_linked": {
          "type": "integer"
        },
        "products_linked": {
          "type": "integer"
        },
        "groups": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "group_products": {
                "type": "integer"
              }
            },
            "required": [
              "id",
              "title",
              "group_products"
            ]
          }
        },
        "products": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The product identifier, returned as a string by the section resource."
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "description"
            ]
          }
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "hidden",
        "order",
        "created_at",
        "updated_at",
        "store_id",
        "groups_linked",
        "products_linked",
        "groups",
        "products"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "title": "Founder resources",
    "slug": "founder-resources",
    "hidden": false,
    "order": 1,
    "created_at": "2026-08-30T12:00:01.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "store_id": 1,
    "groups_linked": 0,
    "products_linked": 0,
    "groups": [],
    "products": []
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/sections/{section}

Retrieve a section

Retrieve a section by its ID.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.get({
  "section": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.get(section=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->get(section: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Sections().Get(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Sections.GetAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.get(section = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.get(section: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let result = client.sections().get("1").await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.get(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections get 1

```

- Method: `GET`

- Path: `/v1/sections/{section}`

- Full URL: `https://sell.app/api/v1/sections/{section}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_SECTION_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/sections/${SELLAPP_SECTION_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `section` (`integer`, required): The section path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": [
            "string",
            "null"
          ]
        },
        "hidden": {
          "type": "boolean"
        },
        "order": {
          "type": "integer"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "groups_linked": {
          "type": "integer"
        },
        "products_linked": {
          "type": "integer"
        },
        "groups": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "group_products": {
                "type": "integer"
              }
            },
            "required": [
              "id",
              "title",
              "group_products"
            ]
          }
        },
        "products": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The product identifier, returned as a string by the section resource."
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "description"
            ]
          }
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "hidden",
        "order",
        "created_at",
        "updated_at",
        "store_id",
        "groups_linked",
        "products_linked",
        "groups",
        "products"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "title": "Dissection",
    "slug": "dissection",
    "hidden": false,
    "order": 1,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "groups_linked": 1,
    "products_linked": 1,
    "groups": [
      {
        "id": 1,
        "title": "Project Planning Toolkit",
        "group_products": 1
      }
    ],
    "products": [
      {
        "id": "1",
        "title": "Project Planning Guide",
        "description": "Includes practical examples and a downloadable checklist."
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v1/sections/{section}

Update a section

Update a storefront section's details.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.update({
  "section": 1,
  "title": "Founder resources",
  "hidden": false
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.update(
    section=1,
    title="Founder resources",
    hidden=False
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->update(
    section: 1,
    title: 'Founder resources',
    hidden: false,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.SectionsUpdateParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Founder resources\",\"hidden\":false}"), params); err != nil { panic(err) }
    result, err := client.Sections().Update(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Sections.UpdateAsync(
    "1",
    new SectionsUpdateOptions
    {
        Title = "Founder resources",
        Hidden = false,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.update(section = "1", title = app.sell.sellapp.common.http.PatchField.Present("Founder resources"), hidden = app.sell.sellapp.common.http.PatchField.Present(false))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.update(
  section: 1,
  title: "Founder resources",
  hidden: false
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::sections::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{\"title\":\"Founder resources\",\"hidden\":false}")?);
    let result = client.sections().update("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.update(client, 1, %{"title" => "Founder resources", "hidden" => false})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections update 1 --title 'Founder resources' --hidden false --yes

```

- Method: `PATCH`

- Path: `/v1/sections/{section}`

- Full URL: `https://sell.app/api/v1/sections/{section}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_SECTION_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v1/sections/${SELLAPP_SECTION_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Founder resources",
  "hidden": false
}'
```

## Path Parameters
- `section` (`integer`, required): The section path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255
    },
    "hidden": {
      "type": "boolean"
    }
  }
}
```

Example:

```json
{
  "title": "Founder resources",
  "hidden": false
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": [
            "string",
            "null"
          ]
        },
        "hidden": {
          "type": "boolean"
        },
        "order": {
          "type": "integer"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "groups_linked": {
          "type": "integer"
        },
        "products_linked": {
          "type": "integer"
        },
        "groups": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "group_products": {
                "type": "integer"
              }
            },
            "required": [
              "id",
              "title",
              "group_products"
            ]
          }
        },
        "products": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The product identifier, returned as a string by the section resource."
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "description"
            ]
          }
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "hidden",
        "order",
        "created_at",
        "updated_at",
        "store_id",
        "groups_linked",
        "products_linked",
        "groups",
        "products"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "title": "Founder resources",
    "slug": "dissection",
    "hidden": false,
    "order": 1,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "store_id": 1,
    "groups_linked": 1,
    "products_linked": 1,
    "groups": [
      {
        "id": 1,
        "title": "Project Planning Toolkit",
        "group_products": 1
      }
    ],
    "products": [
      {
        "id": "1",
        "title": "Project Planning Guide",
        "description": "Includes practical examples and a downloadable checklist."
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## DELETE /v1/sections/{section}

Delete a section

Deletes a section. This will permanently delete the section and its details.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.delete({
  "section": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.delete(section=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->delete(section: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    if err := client.Sections().Delete(context.Background(), 1); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.Sections.DeleteAsync("1");
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.delete(section = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.delete(section: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let result = client.sections().delete("1").await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.delete(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections delete 1 --yes

```

- Method: `DELETE`

- Path: `/v1/sections/{section}`

- Full URL: `https://sell.app/api/v1/sections/{section}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_SECTION_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v1/sections/${SELLAPP_SECTION_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `section` (`integer`, required): The section path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": [
            "string",
            "null"
          ]
        },
        "hidden": {
          "type": "boolean"
        },
        "order": {
          "type": "integer"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "groups_linked": {
          "type": "integer"
        },
        "products_linked": {
          "type": "integer"
        },
        "groups": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "group_products": {
                "type": "integer"
              }
            },
            "required": [
              "id",
              "title",
              "group_products"
            ]
          }
        },
        "products": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The product identifier, returned as a string by the section resource."
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "description"
            ]
          }
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "hidden",
        "order",
        "created_at",
        "updated_at",
        "store_id",
        "groups_linked",
        "products_linked",
        "groups",
        "products"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "title": "Dissection",
    "slug": "dissection",
    "hidden": false,
    "order": 1,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "groups_linked": 1,
    "products_linked": 1,
    "groups": [
      {
        "id": 1,
        "title": "Project Planning Toolkit",
        "group_products": 1
      }
    ],
    "products": [
      {
        "id": "1",
        "title": "Project Planning Guide",
        "description": "Includes practical examples and a downloadable checklist."
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PUT /v1/sections/{section}

Update a section

Update a storefront section's details.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.replace({
  "section": 1,
  "title": "Founder resources",
  "hidden": false
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.replace(
    section=1,
    title="Founder resources",
    hidden=False
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->replace(
    section: 1,
    title: 'Founder resources',
    hidden: false,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.SectionsReplaceParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Founder resources\",\"hidden\":false}"), params); err != nil { panic(err) }
    result, err := client.Sections().Replace(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Sections.ReplaceAsync(
    "1",
    new SectionsReplaceOptions
    {
        Title = "Founder resources",
        Hidden = false,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.replace(section = "1", title = "Founder resources", hidden = false)
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.replace(
  section: 1,
  title: "Founder resources",
  hidden: false
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::sections::ReplaceParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceParams::new(serde_json::from_str("{\"title\":\"Founder resources\",\"hidden\":false}")?);
    let result = client.sections().replace("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.replace(client, 1, %{"title" => "Founder resources", "hidden" => false})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections replace 1 --title 'Founder resources' --hidden false --yes

```

- Method: `PUT`

- Path: `/v1/sections/{section}`

- Full URL: `https://sell.app/api/v1/sections/{section}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_SECTION_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v1/sections/${SELLAPP_SECTION_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Founder resources",
  "hidden": false
}'
```

## Path Parameters
- `section` (`integer`, required): The section path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255
    },
    "hidden": {
      "type": "boolean"
    }
  }
}
```

Example:

```json
{
  "title": "Founder resources",
  "hidden": false
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": [
            "string",
            "null"
          ]
        },
        "hidden": {
          "type": "boolean"
        },
        "order": {
          "type": "integer"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "groups_linked": {
          "type": "integer"
        },
        "products_linked": {
          "type": "integer"
        },
        "groups": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "group_products": {
                "type": "integer"
              }
            },
            "required": [
              "id",
              "title",
              "group_products"
            ]
          }
        },
        "products": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The product identifier, returned as a string by the section resource."
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "description"
            ]
          }
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "hidden",
        "order",
        "created_at",
        "updated_at",
        "store_id",
        "groups_linked",
        "products_linked",
        "groups",
        "products"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "title": "Founder resources",
    "slug": "dissection",
    "hidden": false,
    "order": 1,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "store_id": 1,
    "groups_linked": 1,
    "products_linked": 1,
    "groups": [
      {
        "id": 1,
        "title": "Project Planning Toolkit",
        "group_products": 1
      }
    ],
    "products": [
      {
        "id": "1",
        "title": "Project Planning Guide",
        "description": "Includes practical examples and a downloadable checklist."
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/tickets

List all tickets

List your store's support tickets, 15 per page by default.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.tickets.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.tickets.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->tickets()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.TicketsListParams{}
    page := client.Tickets().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Tickets.ListAsync(new TicketsListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.tickets.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.tickets.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::tickets::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.tickets().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Tickets.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp tickets list

```

- Method: `GET`

- Path: `/v1/tickets`

- Full URL: `https://sell.app/api/v1/tickets`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/tickets" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "customer": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "email": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "email"
            ]
          },
          "reference": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "read_by": {
            "type": "integer"
          },
          "archived": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "title",
          "status",
          "customer",
          "reference",
          "created_at",
          "updated_at",
          "store_id",
          "read_by",
          "archived"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "title": "Payment methods",
      "status": "OPEN",
      "customer": {
        "id": 125,
        "email": "jamie.chen@example.com"
      },
      "reference": [],
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "read_by": 1,
      "archived": 0
    }
  ],
  "links": {
    "first": "https://sell.app/api/v1/tickets?page=1",
    "last": "https://sell.app/api/v1/tickets?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v1/tickets",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v1/tickets?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/tickets/{ticket}

Retrieve specific ticket

Retrieve a support ticket by its ID.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.tickets.get({
  "ticket": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.tickets.get(ticket=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->tickets()->get(ticket: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Tickets().Get(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Tickets.GetAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.tickets.get(ticket = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.tickets.get(ticket: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let result = client.tickets().get("1").await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Tickets.get(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp tickets get 1

```

- Method: `GET`

- Path: `/v1/tickets/{ticket}`

- Full URL: `https://sell.app/api/v1/tickets/{ticket}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_TICKET_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/tickets/${SELLAPP_TICKET_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `ticket` (`integer`, required): The ticket path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "customer": {
          "type": "object",
          "properties": {
            "id": {
              "type": "integer"
            },
            "email": {
              "type": "string"
            }
          },
          "required": [
            "id",
            "email"
          ]
        },
        "reference": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "read_by": {
          "type": "integer"
        },
        "archived": {
          "type": "integer"
        }
      },
      "required": [
        "id",
        "title",
        "status",
        "customer",
        "reference",
        "created_at",
        "updated_at",
        "store_id",
        "read_by",
        "archived"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "title": "Payment methods",
    "status": "OPEN",
    "customer": {
      "id": 125,
      "email": "jamie.chen@example.com"
    },
    "reference": [],
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "read_by": 1,
    "archived": 0
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/tickets/{ticket}/messages

List all ticket messages

Read a ticket's conversation, 15 messages per page by default.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.ticketsMessages.list({
  "ticket": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.tickets_messages.list(ticket=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->ticketsMessages()->list(ticket: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.TicketsMessagesListParams{}
    page := client.TicketsMessages().List(context.Background(), 1, params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.TicketsMessages.ListAsync(
    "1",
    new TicketsMessagesListOptions
    {
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.ticketsMessages.list(ticket = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.tickets_messages.list(ticket: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::tickets_messages::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.tickets_messages().list("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.TicketsMessages.list(client, 1, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp tickets messages list 1

```

- Method: `GET`

- Path: `/v1/tickets/{ticket}/messages`

- Full URL: `https://sell.app/api/v1/tickets/{ticket}/messages`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_TICKET_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/tickets/${SELLAPP_TICKET_ID}/messages" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `ticket` (`integer`, required): The ticket path parameter.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "author": {
            "type": "string"
          },
          "sender": {
            "type": [
              "string",
              "null"
            ]
          },
          "content": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "ticket_id": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "author",
          "sender",
          "content",
          "created_at",
          "updated_at",
          "ticket_id"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "author": "CUSTOMER",
      "sender": "jamie.chen@example.com",
      "content": "Hello, which payment methods can I use for this purchase?",
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "ticket_id": 1
    }
  ],
  "links": {
    "first": "https://sell.app/api/v1/tickets/1/messages?page=1",
    "last": "https://sell.app/api/v1/tickets/1/messages?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v1/tickets/1/messages",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v1/tickets/1/messages?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/tickets/{ticket}/messages

Reply to ticket

Add a seller reply to a support conversation.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.ticketsMessages.reply({
  "ticket": 1,
  "content": "You can choose from the payment methods shown at checkout."
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.tickets_messages.reply(
    ticket=1,
    content="You can choose from the payment methods shown at checkout."
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->ticketsMessages()->reply(
    ticket: 1,
    content: 'You can choose from the payment methods shown at checkout.',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.TicketsMessagesReplyParams{}
    if err := json.Unmarshal([]byte("{\"content\":\"You can choose from the payment methods shown at checkout.\"}"), params); err != nil { panic(err) }
    result, err := client.TicketsMessages().Reply(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.TicketsMessages.ReplyAsync(
    "1",
    new TicketsMessagesReplyOptions
    {
        Content = "You can choose from the payment methods shown at checkout.",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.ticketsMessages.reply(ticket = "1", content = "You can choose from the payment methods shown at checkout.")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.tickets_messages.reply(
  ticket: 1,
  content: "You can choose from the payment methods shown at checkout."
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::tickets_messages::ReplyParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplyParams::new(serde_json::from_str("{\"content\":\"You can choose from the payment methods shown at checkout.\"}")?);
    let result = client.tickets_messages().reply("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.TicketsMessages.reply(client, 1, %{"content" => "You can choose from the payment methods shown at checkout."})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp tickets messages reply 1 --content 'You can choose from the payment methods shown at checkout.' --yes

```

- Method: `POST`

- Path: `/v1/tickets/{ticket}/messages`

- Full URL: `https://sell.app/api/v1/tickets/{ticket}/messages`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_TICKET_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/tickets/${SELLAPP_TICKET_ID}/messages" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "content": "You can choose from the payment methods shown at checkout."
}'
```

## Path Parameters
- `ticket` (`integer`, required): The ticket path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "content": {
      "type": "string"
    }
  },
  "required": [
    "content"
  ]
}
```

Example:

```json
{
  "content": "You can choose from the payment methods shown at checkout."
}
```

## Responses

### 201

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "author": {
          "type": "string"
        },
        "sender": {
          "type": [
            "string",
            "null"
          ],
          "description": "The seller who wrote the reply, or null on a message the customer wrote."
        },
        "content": {
          "type": "string"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "ticket_id": {
          "type": "integer"
        }
      },
      "required": [
        "id",
        "author",
        "sender",
        "content",
        "created_at",
        "updated_at",
        "ticket_id"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 2,
    "author": "STORE",
    "sender": null,
    "content": "You can choose from the payment methods shown at checkout.",
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "ticket_id": 1
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/tickets/{ticket}/messages/{message}

Retrieve specific ticket message

Retrieve one message using its ticket ID and message ID.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.ticketsMessages.get({
  "ticket": 1,
  "message": 2
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.tickets_messages.get(
    ticket=1,
    message=2
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->ticketsMessages()->get(
    ticket: 1,
    message: 2,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.TicketsMessages().Get(context.Background(), 1, 2)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.TicketsMessages.GetAsync(
    "1",
    "2"
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.ticketsMessages.get(ticket = "1", message = "2")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.tickets_messages.get(
  ticket: 1,
  message: 2
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let result = client.tickets_messages().get("1", "2").await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.TicketsMessages.get(client, 1, 2)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp tickets messages get --ticket 1 2

```

- Method: `GET`

- Path: `/v1/tickets/{ticket}/messages/{message}`

- Full URL: `https://sell.app/api/v1/tickets/{ticket}/messages/{message}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_TICKET_ID='1'
export SELLAPP_MESSAGE_ID='2'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/tickets/${SELLAPP_TICKET_ID}/messages/${SELLAPP_MESSAGE_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `ticket` (`integer`, required): The ticket path parameter.
- `message` (`integer`, required): The message path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "author": {
          "type": "string"
        },
        "sender": {
          "type": [
            "string",
            "null"
          ],
          "description": "The seller who wrote the reply, or null on a message the customer wrote."
        },
        "content": {
          "type": "string"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "ticket_id": {
          "type": "integer"
        }
      },
      "required": [
        "id",
        "author",
        "sender",
        "content",
        "created_at",
        "updated_at",
        "ticket_id"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 2,
    "author": "STORE",
    "sender": null,
    "content": "You can choose from the payment methods shown at checkout.",
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "ticket_id": 1
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/tickets/search

Search tickets

Search tickets using JSON body filters, search terms, includes, and sort instructions.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.tickets.search({
  "filters": [{"field": "id", "operator": "=", "value": 1}],
  "sort": [{"field": "created_at", "direction": "desc"}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.tickets.search(
    filters=[{"field": "id", "operator": "=", "value": 1}],
    sort=[{"field": "created_at", "direction": "desc"}]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->tickets()->search(
    filters: [['field' => 'id', 'operator' => '=', 'value' => 1]],
    sort: [['field' => 'created_at', 'direction' => 'desc']],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.TicketsSearchParams{}
    if err := json.Unmarshal([]byte("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}"), params); err != nil { panic(err) }
    page := client.Tickets().Search(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Tickets.SearchAsync(new TicketsSearchOptions
    {
        Filters = JsonConvert.DeserializeObject<List<SearchTicketsRequestApplicationJsonPropertyFiltersItem>>("[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}]")!,
        Sort = JsonConvert.DeserializeObject<List<SearchTicketsRequestApplicationJsonPropertySortItem>>("[{\"field\":\"created_at\",\"direction\":\"desc\"}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.tickets.search(filters = listOf(ObjectMapperFactory.read("{\"field\":\"id\",\"operator\":\"=\",\"value\":1}", app.sell.sellapp.models.SearchTicketsRequestApplicationJsonPropertyFiltersItem::class.java)), sort = listOf(ObjectMapperFactory.read("{\"field\":\"created_at\",\"direction\":\"desc\"}", app.sell.sellapp.models.SearchTicketsRequestApplicationJsonPropertySortItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.tickets.search(
  filters: [{ field: "id", operator: "=", value: 1 }],
  sort: [{ field: "created_at", direction: "desc" }]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::tickets::SearchParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = SearchParams::new(serde_json::from_str("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}")?);
    let result = client.tickets().search(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Tickets.search(client, %{"filters" => [%{"field" => "id", "operator" => "=", "value" => 1}], "sort" => [%{"field" => "created_at", "direction" => "desc"}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp tickets search --body '{"filters":[{"field":"id","operator":"=","value":1}],"sort":[{"field":"created_at","direction":"desc"}]}'

```

- Method: `POST`

- Path: `/v1/tickets/search`

- Full URL: `https://sell.app/api/v1/tickets/search`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/tickets/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "operator": {
            "type": "string",
            "default": "="
          },
          "value": {},
          "type": {
            "type": "string",
            "enum": [
              "and",
              "or"
            ],
            "default": "and"
          },
          "nested": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "anyOf": [
          {
            "required": [
              "field"
            ]
          },
          {
            "required": [
              "nested"
            ]
          }
        ]
      }
    },
    "sort": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "default": "asc"
          }
        },
        "required": [
          "field"
        ]
      }
    },
    "search": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "null"
          ]
        },
        "case_sensitive": {
          "type": "boolean"
        }
      }
    },
    "includes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "relation": {
            "type": "string"
          }
        },
        "required": [
          "relation"
        ]
      }
    }
  }
}
```

Example:

```json
{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "customer": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "email": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "email"
            ]
          },
          "reference": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "read_by": {
            "type": "integer"
          },
          "archived": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "title",
          "status",
          "customer",
          "reference",
          "created_at",
          "updated_at",
          "store_id",
          "read_by",
          "archived"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "title": "Payment methods",
      "status": "OPEN",
      "customer": {
        "id": 125,
        "email": "jamie.chen@example.com"
      },
      "reference": [],
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "read_by": 1,
      "archived": 0
    }
  ],
  "links": {
    "first": "https://sell.app/api/v1/tickets/search?page=1",
    "last": "https://sell.app/api/v1/tickets/search?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v1/tickets/search",
    "per_page": 20,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v1/tickets/search?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/tickets/{ticket}/messages/search

Search ticket messages

Search a ticket's messages using JSON body filters, search terms, includes, and sort instructions.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.ticketsMessages.search({
  "ticket": 1,
  "filters": [{"field": "id", "operator": "=", "value": 1}],
  "sort": [{"field": "created_at", "direction": "desc"}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.tickets_messages.search(
    ticket=1,
    filters=[{"field": "id", "operator": "=", "value": 1}],
    sort=[{"field": "created_at", "direction": "desc"}]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->ticketsMessages()->search(
    ticket: 1,
    filters: [['field' => 'id', 'operator' => '=', 'value' => 1]],
    sort: [['field' => 'created_at', 'direction' => 'desc']],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.TicketsMessagesSearchParams{}
    if err := json.Unmarshal([]byte("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}"), params); err != nil { panic(err) }
    page := client.TicketsMessages().Search(context.Background(), 1, params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.TicketsMessages.SearchAsync(
    "1",
    new TicketsMessagesSearchOptions
    {
        Filters = JsonConvert.DeserializeObject<List<SearchTicketMessagesRequestApplicationJsonPropertyFiltersItem>>("[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}]")!,
        Sort = JsonConvert.DeserializeObject<List<SearchTicketMessagesRequestApplicationJsonPropertySortItem>>("[{\"field\":\"created_at\",\"direction\":\"desc\"}]")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.ticketsMessages.search(ticket = "1", filters = listOf(ObjectMapperFactory.read("{\"field\":\"id\",\"operator\":\"=\",\"value\":1}", app.sell.sellapp.models.SearchTicketMessagesRequestApplicationJsonPropertyFiltersItem::class.java)), sort = listOf(ObjectMapperFactory.read("{\"field\":\"created_at\",\"direction\":\"desc\"}", app.sell.sellapp.models.SearchTicketMessagesRequestApplicationJsonPropertySortItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.tickets_messages.search(
  ticket: 1,
  filters: [{ field: "id", operator: "=", value: 1 }],
  sort: [{ field: "created_at", direction: "desc" }]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::tickets_messages::SearchParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = SearchParams::new(serde_json::from_str("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}")?);
    let result = client.tickets_messages().search("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.TicketsMessages.search(client, 1, %{"filters" => [%{"field" => "id", "operator" => "=", "value" => 1}], "sort" => [%{"field" => "created_at", "direction" => "desc"}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp tickets messages search 1 --body '{"filters":[{"field":"id","operator":"=","value":1}],"sort":[{"field":"created_at","direction":"desc"}]}'

```

- Method: `POST`

- Path: `/v1/tickets/{ticket}/messages/search`

- Full URL: `https://sell.app/api/v1/tickets/{ticket}/messages/search`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_TICKET_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/tickets/${SELLAPP_TICKET_ID}/messages/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}'
```

## Path Parameters
- `ticket` (`integer`, required): The ticket path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "operator": {
            "type": "string",
            "default": "="
          },
          "value": {},
          "type": {
            "type": "string",
            "enum": [
              "and",
              "or"
            ],
            "default": "and"
          },
          "nested": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "anyOf": [
          {
            "required": [
              "field"
            ]
          },
          {
            "required": [
              "nested"
            ]
          }
        ]
      }
    },
    "sort": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "default": "asc"
          }
        },
        "required": [
          "field"
        ]
      }
    },
    "search": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "null"
          ]
        },
        "case_sensitive": {
          "type": "boolean"
        }
      }
    },
    "includes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "relation": {
            "type": "string"
          }
        },
        "required": [
          "relation"
        ]
      }
    }
  }
}
```

Example:

```json
{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "author": {
            "type": "string"
          },
          "sender": {
            "type": [
              "string",
              "null"
            ]
          },
          "content": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "ticket_id": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "author",
          "sender",
          "content",
          "created_at",
          "updated_at",
          "ticket_id"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "author": "CUSTOMER",
      "sender": "jamie.chen@example.com",
      "content": "Hello, which payment methods can I use for this purchase?",
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "ticket_id": 1
    }
  ],
  "links": {
    "first": "https://sell.app/api/v1/tickets/1/messages/search?page=1",
    "last": "https://sell.app/api/v1/tickets/1/messages/search?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v1/tickets/1/messages/search",
    "per_page": 20,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v1/tickets/1/messages/search?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/feedback/search

Search feedback

Search feedback using JSON body filters, search terms, includes, and sort instructions.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.feedback.search({
  "filters": [{"field": "id", "operator": "=", "value": 1}],
  "sort": [{"field": "created_at", "direction": "desc"}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.feedback.search(
    filters=[{"field": "id", "operator": "=", "value": 1}],
    sort=[{"field": "created_at", "direction": "desc"}]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->feedback()->search(
    filters: [['field' => 'id', 'operator' => '=', 'value' => 1]],
    sort: [['field' => 'created_at', 'direction' => 'desc']],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.FeedbackSearchParams{}
    if err := json.Unmarshal([]byte("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}"), params); err != nil { panic(err) }
    page := client.Feedback().Search(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Feedback.SearchAsync(new FeedbackSearchOptions
    {
        Filters = JsonConvert.DeserializeObject<List<SearchFeedbackRequestApplicationJsonPropertyFiltersItem>>("[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}]")!,
        Sort = JsonConvert.DeserializeObject<List<SearchFeedbackRequestApplicationJsonPropertySortItem>>("[{\"field\":\"created_at\",\"direction\":\"desc\"}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.feedback.search(filters = listOf(ObjectMapperFactory.read("{\"field\":\"id\",\"operator\":\"=\",\"value\":1}", app.sell.sellapp.models.SearchFeedbackRequestApplicationJsonPropertyFiltersItem::class.java)), sort = listOf(ObjectMapperFactory.read("{\"field\":\"created_at\",\"direction\":\"desc\"}", app.sell.sellapp.models.SearchFeedbackRequestApplicationJsonPropertySortItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.feedback.search(
  filters: [{ field: "id", operator: "=", value: 1 }],
  sort: [{ field: "created_at", direction: "desc" }]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::feedback::SearchParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = SearchParams::new(serde_json::from_str("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}")?);
    let result = client.feedback().search(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Feedback.search(client, %{"filters" => [%{"field" => "id", "operator" => "=", "value" => 1}], "sort" => [%{"field" => "created_at", "direction" => "desc"}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp feedback search --body '{"filters":[{"field":"id","operator":"=","value":1}],"sort":[{"field":"created_at","direction":"desc"}]}'

```

- Method: `POST`

- Path: `/v1/feedback/search`

- Full URL: `https://sell.app/api/v1/feedback/search`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/feedback/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "operator": {
            "type": "string",
            "default": "="
          },
          "value": {},
          "type": {
            "type": "string",
            "enum": [
              "and",
              "or"
            ],
            "default": "and"
          },
          "nested": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "anyOf": [
          {
            "required": [
              "field"
            ]
          },
          {
            "required": [
              "nested"
            ]
          }
        ]
      }
    },
    "sort": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "default": "asc"
          }
        },
        "required": [
          "field"
        ]
      }
    },
    "search": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "null"
          ]
        },
        "case_sensitive": {
          "type": "boolean"
        }
      }
    },
    "includes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "relation": {
            "type": "string"
          }
        },
        "required": [
          "relation"
        ]
      }
    }
  }
}
```

Example:

```json
{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "feedback": {
            "type": "string"
          },
          "rating": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "listing_id": {
            "type": "integer"
          },
          "invoice_id": {
            "type": "integer"
          },
          "store_id": {
            "type": "integer"
          },
          "metadata": {
            "anyOf": [
              {
                "type": "object",
                "description": "Import details recorded when the feedback came from another platform, or null when the customer left it in the store.",
                "properties": {
                  "imported_from": {
                    "type": "string"
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "message": {
            "type": "string"
          },
          "reply": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_automatic": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "feedback",
          "rating",
          "deleted_at",
          "created_at",
          "updated_at",
          "listing_id",
          "invoice_id",
          "store_id",
          "metadata",
          "message",
          "reply",
          "is_automatic"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "feedback": "POSITIVE",
      "rating": 5,
      "deleted_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "listing_id": 1,
      "invoice_id": 1,
      "store_id": 1,
      "metadata": null,
      "message": "The download arrived immediately and the setup instructions were clear.",
      "reply": "Thank you for your feedback.",
      "is_automatic": true
    }
  ],
  "links": {
    "first": "https://sell.app/api/v1/feedback/search?page=1",
    "last": "https://sell.app/api/v1/feedback/search?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v1/feedback/search",
    "per_page": 20,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v1/feedback/search?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PUT /v1/sections/order

Replace section order

Replace the storefront section order with every section ID in the store. IDs are applied in array order; incomplete lists and unknown IDs are rejected.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.replaceOrder({
  "resources": [3, 1, 2]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.replace_order(resources=[3, 1, 2])
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->replaceOrder(resources: [3, 1, 2]);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.SectionsReplaceOrderParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[3,1,2]}"), params); err != nil { panic(err) }
    result, err := client.Sections().ReplaceOrder(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Sections.ReplaceOrderAsync(new SectionsReplaceOrderOptions
    {
        Resources = JsonConvert.DeserializeObject<List<long>>("[3,1,2]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.replaceOrder(resources = listOf(3L, 1L, 2L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.replace_order(resources: [3, 1, 2])
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::sections::ReplaceOrderParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceOrderParams::new(serde_json::from_str("{\"resources\":[3,1,2]}")?);
    let result = client.sections().replace_order(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.replace_order(client, %{"resources" => [3, 1, 2]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections replace-order --body '{"resources":[3,1,2]}' --yes

```

- Method: `PUT`

- Path: `/v1/sections/order`

- Full URL: `https://sell.app/api/v1/sections/order`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v1/sections/order" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    3,
    1,
    2
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "uniqueItems": true
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    3,
    1,
    2
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "hidden": {
            "type": "boolean"
          },
          "order": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "groups_linked": {
            "type": "integer"
          },
          "products_linked": {
            "type": "integer"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "title": {
                  "type": "string"
                },
                "group_products": {
                  "type": "integer"
                }
              },
              "required": [
                "id",
                "title",
                "group_products"
              ]
            }
          },
          "products": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The product identifier, returned as a string by the section resource."
                },
                "title": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "title",
                "description"
              ]
            }
          }
        },
        "required": [
          "id",
          "title",
          "slug",
          "hidden",
          "order",
          "created_at",
          "updated_at",
          "store_id",
          "groups_linked",
          "products_linked",
          "groups",
          "products"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 3,
      "title": "Founder resources 3",
      "slug": "founder-resources-3",
      "hidden": false,
      "order": 1,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "groups_linked": 1,
      "products_linked": 1,
      "groups": [
        {
          "id": 1,
          "title": "Project Planning Toolkit",
          "group_products": 1
        }
      ],
      "products": [
        {
          "id": "1",
          "title": "Project Planning Guide",
          "description": "Includes practical examples and a downloadable checklist."
        }
      ]
    },
    {
      "id": 1,
      "title": "Founder resources 1",
      "slug": "founder-resources-1",
      "hidden": false,
      "order": 2,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "groups_linked": 1,
      "products_linked": 1,
      "groups": [
        {
          "id": 1,
          "title": "Project Planning Toolkit",
          "group_products": 1
        }
      ],
      "products": [
        {
          "id": "1",
          "title": "Project Planning Guide",
          "description": "Includes practical examples and a downloadable checklist."
        }
      ]
    },
    {
      "id": 2,
      "title": "Founder resources 2",
      "slug": "founder-resources-2",
      "hidden": false,
      "order": 3,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "groups_linked": 1,
      "products_linked": 1,
      "groups": [
        {
          "id": 1,
          "title": "Project Planning Toolkit",
          "group_products": 1
        }
      ],
      "products": [
        {
          "id": "1",
          "title": "Project Planning Guide",
          "description": "Includes practical examples and a downloadable checklist."
        }
      ]
    }
  ]
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PUT /v1/sections/{section}/products

Replace section products

Replace the products assigned to a section. Product IDs are stored in the supplied order; omitted products are detached and unknown IDs are rejected.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.replaceProducts({
  "section": 1,
  "resources": [3, 1, 2]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.replace_products(
    section=1,
    resources=[3, 1, 2]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->replaceProducts(
    section: 1,
    resources: [3, 1, 2],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.SectionsReplaceProductsParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[3,1,2]}"), params); err != nil { panic(err) }
    result, err := client.Sections().ReplaceProducts(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Sections.ReplaceProductsAsync(
    "1",
    new SectionsReplaceProductsOptions
    {
        Resources = JsonConvert.DeserializeObject<List<long>>("[3,1,2]")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.replaceProducts(section = "1", resources = listOf(3L, 1L, 2L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.replace_products(
  section: 1,
  resources: [3, 1, 2]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::sections::ReplaceProductsParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceProductsParams::new(serde_json::from_str("{\"resources\":[3,1,2]}")?);
    let result = client.sections().replace_products("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.replace_products(client, 1, %{"resources" => [3, 1, 2]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections replace-products 1 --body '{"resources":[3,1,2]}' --yes

```

- Method: `PUT`

- Path: `/v1/sections/{section}/products`

- Full URL: `https://sell.app/api/v1/sections/{section}/products`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_SECTION_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v1/sections/${SELLAPP_SECTION_ID}/products" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    3,
    1,
    2
  ]
}'
```

## Path Parameters
- `section` (`integer`, required): The section path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "uniqueItems": true
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    3,
    1,
    2
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": [
            "string",
            "null"
          ]
        },
        "hidden": {
          "type": "boolean"
        },
        "order": {
          "type": "integer"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "groups_linked": {
          "type": "integer"
        },
        "products_linked": {
          "type": "integer"
        },
        "groups": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "group_products": {
                "type": "integer"
              }
            },
            "required": [
              "id",
              "title",
              "group_products"
            ]
          }
        },
        "products": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The product identifier, returned as a string by the section resource."
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "description"
            ]
          }
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "hidden",
        "order",
        "created_at",
        "updated_at",
        "store_id",
        "groups_linked",
        "products_linked",
        "groups",
        "products"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "title": "Dissection",
    "slug": "dissection",
    "hidden": false,
    "order": 1,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "groups_linked": 1,
    "products_linked": 3,
    "groups": [
      {
        "id": 1,
        "title": "Project Planning Toolkit",
        "group_products": 1
      }
    ],
    "products": [
      {
        "id": "3",
        "title": "Project Planning Guide",
        "description": "Includes practical examples and a downloadable checklist."
      },
      {
        "id": "1",
        "title": "Project Planning Guide",
        "description": "Includes practical examples and a downloadable checklist."
      },
      {
        "id": "2",
        "title": "Project Planning Guide",
        "description": "Includes practical examples and a downloadable checklist."
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PUT /v1/sections/{section}/groups

Replace section groups

Replace the groups assigned to a section. Group IDs are stored in the supplied order; omitted groups are detached and unknown IDs are rejected.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.replaceGroups({
  "section": 1,
  "resources": [3, 1, 2]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.replace_groups(
    section=1,
    resources=[3, 1, 2]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->replaceGroups(
    section: 1,
    resources: [3, 1, 2],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.SectionsReplaceGroupsParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[3,1,2]}"), params); err != nil { panic(err) }
    result, err := client.Sections().ReplaceGroups(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Sections.ReplaceGroupsAsync(
    "1",
    new SectionsReplaceGroupsOptions
    {
        Resources = JsonConvert.DeserializeObject<List<long>>("[3,1,2]")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.replaceGroups(section = "1", resources = listOf(3L, 1L, 2L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.replace_groups(
  section: 1,
  resources: [3, 1, 2]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::sections::ReplaceGroupsParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceGroupsParams::new(serde_json::from_str("{\"resources\":[3,1,2]}")?);
    let result = client.sections().replace_groups("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.replace_groups(client, 1, %{"resources" => [3, 1, 2]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections replace-groups 1 --body '{"resources":[3,1,2]}' --yes

```

- Method: `PUT`

- Path: `/v1/sections/{section}/groups`

- Full URL: `https://sell.app/api/v1/sections/{section}/groups`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_SECTION_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v1/sections/${SELLAPP_SECTION_ID}/groups" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    3,
    1,
    2
  ]
}'
```

## Path Parameters
- `section` (`integer`, required): The section path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "uniqueItems": true
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    3,
    1,
    2
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": [
            "string",
            "null"
          ]
        },
        "hidden": {
          "type": "boolean"
        },
        "order": {
          "type": "integer"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "groups_linked": {
          "type": "integer"
        },
        "products_linked": {
          "type": "integer"
        },
        "groups": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "group_products": {
                "type": "integer"
              }
            },
            "required": [
              "id",
              "title",
              "group_products"
            ]
          }
        },
        "products": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The product identifier, returned as a string by the section resource."
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "description"
            ]
          }
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "hidden",
        "order",
        "created_at",
        "updated_at",
        "store_id",
        "groups_linked",
        "products_linked",
        "groups",
        "products"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "title": "Dissection",
    "slug": "dissection",
    "hidden": false,
    "order": 1,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "groups_linked": 3,
    "products_linked": 1,
    "groups": [
      {
        "id": 3,
        "title": "Project Planning Toolkit",
        "group_products": 1
      },
      {
        "id": 1,
        "title": "Project Planning Toolkit",
        "group_products": 1
      },
      {
        "id": 2,
        "title": "Project Planning Toolkit",
        "group_products": 1
      }
    ],
    "products": [
      {
        "id": "1",
        "title": "Project Planning Guide",
        "description": "Includes practical examples and a downloadable checklist."
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/coupons/search

Search coupons

Search coupons using JSON body filters, search terms, includes, and sort instructions.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.search({
  "filters": [{"field": "id", "operator": "=", "value": 1}],
  "sort": [{"field": "created_at", "direction": "desc"}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.search(
    filters=[{"field": "id", "operator": "=", "value": 1}],
    sort=[{"field": "created_at", "direction": "desc"}]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->search(
    filters: [['field' => 'id', 'operator' => '=', 'value' => 1]],
    sort: [['field' => 'created_at', 'direction' => 'desc']],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsSearchParams{}
    if err := json.Unmarshal([]byte("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}"), params); err != nil { panic(err) }
    page := client.Coupons().Search(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.SearchAsync(new CouponsSearchOptions
    {
        Filters = JsonConvert.DeserializeObject<List<SearchCouponsRequestApplicationJsonPropertyFiltersItem>>("[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}]")!,
        Sort = JsonConvert.DeserializeObject<List<SearchCouponsRequestApplicationJsonPropertySortItem>>("[{\"field\":\"created_at\",\"direction\":\"desc\"}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.search(filters = listOf(ObjectMapperFactory.read("{\"field\":\"id\",\"operator\":\"=\",\"value\":1}", app.sell.sellapp.models.SearchCouponsRequestApplicationJsonPropertyFiltersItem::class.java)), sort = listOf(ObjectMapperFactory.read("{\"field\":\"created_at\",\"direction\":\"desc\"}", app.sell.sellapp.models.SearchCouponsRequestApplicationJsonPropertySortItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.search(
  filters: [{ field: "id", operator: "=", value: 1 }],
  sort: [{ field: "created_at", direction: "desc" }]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::SearchParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = SearchParams::new(serde_json::from_str("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}")?);
    let result = client.coupons().search(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.search(client, %{"filters" => [%{"field" => "id", "operator" => "=", "value" => 1}], "sort" => [%{"field" => "created_at", "direction" => "desc"}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons search --body '{"filters":[{"field":"id","operator":"=","value":1}],"sort":[{"field":"created_at","direction":"desc"}]}'

```

- Method: `POST`

- Path: `/v1/coupons/search`

- Full URL: `https://sell.app/api/v1/coupons/search`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/coupons/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "operator": {
            "type": "string",
            "default": "="
          },
          "value": {},
          "type": {
            "type": "string",
            "enum": [
              "and",
              "or"
            ],
            "default": "and"
          },
          "nested": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "anyOf": [
          {
            "required": [
              "field"
            ]
          },
          {
            "required": [
              "nested"
            ]
          }
        ]
      }
    },
    "sort": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "default": "asc"
          }
        },
        "required": [
          "field"
        ]
      }
    },
    "search": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "null"
          ]
        },
        "case_sensitive": {
          "type": "boolean"
        }
      }
    },
    "includes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "relation": {
            "type": "string"
          }
        },
        "required": [
          "relation"
        ]
      }
    }
  }
}
```

Example:

```json
{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": "string"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "store_wide": {
            "type": "boolean"
          },
          "minimum_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
            "example": "2026-07-03 12:15:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "maximum_discount_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
          },
          "products": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "discount",
          "limit",
          "store_wide",
          "minimum_amount",
          "expires_at",
          "created_at",
          "updated_at",
          "store_id",
          "deleted_at",
          "maximum_discount_amount",
          "products",
          "product_variants"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "code": "BONANZA",
      "type": "PERCENTAGE",
      "discount": "80",
      "limit": null,
      "store_wide": true,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "deleted_at": null,
      "products": [],
      "product_variants": [],
      "maximum_discount_amount": null
    }
  ],
  "links": {
    "first": "https://sell.app/api/v1/coupons/search?page=1",
    "last": "https://sell.app/api/v1/coupons/search?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v1/coupons/search",
    "per_page": 20,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v1/coupons/search?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/coupons/batch

Batch create coupons

Create multiple coupons in one request by sending a `resources` array.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.batchCreate({
  "resources": [{"code": "STARTER10", "type": "PERCENTAGE", "discount": 10, "storeWide": false, "products": [123], "productVariants": [1001]}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.batch_create(
    resources=[
        {
            "code": "STARTER10",
            "type": "PERCENTAGE",
            "discount": 10,
            "store_wide": False,
            "products": [123],
            "product_variants": [1001]
        }
    ]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->batchCreate(
    resources: [
        [
            'code' => 'STARTER10',
            'type' => 'PERCENTAGE',
            'discount' => 10,
            'store_wide' => false,
            'products' => [123],
            'product_variants' => [1001],
        ],
    ],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsBatchCreateParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[{\"code\":\"STARTER10\",\"type\":\"PERCENTAGE\",\"discount\":10,\"store_wide\":false,\"products\":[123],\"product_variants\":[1001]}]}"), params); err != nil { panic(err) }
    result, err := client.Coupons().BatchCreate(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.BatchCreateAsync(new CouponsBatchCreateOptions
    {
        Resources = JsonConvert.DeserializeObject<List<BatchCreateCouponsRequestApplicationJsonPropertyResourcesItem>>("[{\"code\":\"STARTER10\",\"type\":\"PERCENTAGE\",\"discount\":10,\"store_wide\":false,\"products\":[123],\"product_variants\":[1001]}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.batchCreate(resources = listOf(ObjectMapperFactory.read("{\"code\":\"STARTER10\",\"type\":\"PERCENTAGE\",\"discount\":10,\"store_wide\":false,\"products\":[123],\"product_variants\":[1001]}", app.sell.sellapp.models.BatchCreateCouponsRequestApplicationJsonPropertyResourcesItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.batch_create(
  resources: [
    {
      code: "STARTER10",
      type: "PERCENTAGE",
      discount: 10,
      store_wide: false,
      products: [123],
      product_variants: [1001]
    }
  ]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::BatchCreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = BatchCreateParams::new(serde_json::from_str("{\"resources\":[{\"code\":\"STARTER10\",\"type\":\"PERCENTAGE\",\"discount\":10,\"store_wide\":false,\"products\":[123],\"product_variants\":[1001]}]}")?);
    let result = client.coupons().batch_create(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.batch_create(client, %{"resources" => [%{"code" => "STARTER10", "type" => "PERCENTAGE", "discount" => 10, "store_wide" => false, "products" => [123], "product_variants" => [1001]}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons batch-create --body '{"resources":[{"code":"STARTER10","type":"PERCENTAGE","discount":10,"store_wide":false,"products":[123],"product_variants":[1001]}]}' --yes

```

- Method: `POST`

- Path: `/v1/coupons/batch`

- Full URL: `https://sell.app/api/v1/coupons/batch`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/coupons/batch" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    {
      "code": "STARTER10",
      "type": "PERCENTAGE",
      "discount": 10,
      "store_wide": false,
      "products": [
        123
      ],
      "product_variants": [
        1001
      ]
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 255
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": [
              "number",
              "string"
            ],
            "minimum": 1,
            "maxLength": 255,
            "description": "A decimal discount value of at least 1. Percentage discounts cannot exceed 100; amount discounts use the store currency's major unit."
          },
          "store_wide": {
            "type": "boolean"
          },
          "products": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "integer"
            },
            "description": "Product IDs the coupon applies to when store_wide is false."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Optional variant restrictions. Every variant must belong to a selected product. Products without listed variants remain eligible on all variants."
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "A future date and time, or null for no expiry."
          },
          "minimum_amount": {
            "type": [
              "number",
              "string",
              "null"
            ],
            "minimum": 1,
            "maxLength": 255,
            "description": "A decimal minimum order amount in the store currency's major unit, or null for no minimum."
          }
        },
        "required": [
          "code",
          "type",
          "discount",
          "store_wide"
        ]
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    {
      "code": "STARTER10",
      "type": "PERCENTAGE",
      "discount": 10,
      "store_wide": false,
      "products": [
        123
      ],
      "product_variants": [
        1001
      ]
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": "string"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "store_wide": {
            "type": "boolean"
          },
          "minimum_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
            "example": "2026-07-03 12:15:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "maximum_discount_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
          },
          "products": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "discount",
          "limit",
          "store_wide",
          "minimum_amount",
          "expires_at",
          "created_at",
          "updated_at",
          "store_id",
          "deleted_at",
          "maximum_discount_amount",
          "products",
          "product_variants"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "code": "STARTER10",
      "type": "PERCENTAGE",
      "discount": "10",
      "limit": null,
      "store_wide": false,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2026-08-30T12:00:01.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "deleted_at": null,
      "products": [
        123
      ],
      "product_variants": [
        1001
      ],
      "maximum_discount_amount": null
    }
  ]
}
```

### 201

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": "string"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "store_wide": {
            "type": "boolean"
          },
          "minimum_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
            "example": "2026-07-03 12:15:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "maximum_discount_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
          },
          "products": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "discount",
          "limit",
          "store_wide",
          "minimum_amount",
          "expires_at",
          "created_at",
          "updated_at",
          "store_id",
          "deleted_at",
          "maximum_discount_amount",
          "products",
          "product_variants"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "code": "STARTER10",
      "type": "PERCENTAGE",
      "discount": "10",
      "limit": null,
      "store_wide": false,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2026-08-30T12:00:01.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "deleted_at": null,
      "products": [
        123
      ],
      "product_variants": [
        1001
      ],
      "maximum_discount_amount": null
    }
  ]
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v1/coupons/batch

Batch update coupons

Update multiple coupons in one request by sending a `resources` object keyed by coupon ID.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.batchUpdate({
  "resources": {"1": {"store_wide":false,"products":[123],"product_variants":[1001,1002]}}
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.batch_update(
    resources={
        "1": {"store_wide": False, "products": [123], "product_variants": [1001, 1002]}
    }
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->batchUpdate(
    resources: [
        '1' => ['store_wide' => false, 'products' => [123], 'product_variants' => [1001, 1002]],
    ],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsBatchUpdateParams{}
    if err := json.Unmarshal([]byte("{\"resources\":{\"1\":{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}}}"), params); err != nil { panic(err) }
    result, err := client.Coupons().BatchUpdate(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.BatchUpdateAsync(new CouponsBatchUpdateOptions
    {
        Resources = JsonConvert.DeserializeObject<BatchUpdateCouponsRequestApplicationJsonPropertyResources>("{\"1\":{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}}")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.batchUpdate(resources = ObjectMapperFactory.read("{\"1\":{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}}", app.sell.sellapp.models.BatchUpdateCouponsRequestApplicationJsonPropertyResources::class.java))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.batch_update(
  resources: {
    "1" => { store_wide: false, products: [123], product_variants: [1001, 1002] }
  }
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::BatchUpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = BatchUpdateParams::new(serde_json::from_str("{\"resources\":{\"1\":{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}}}")?);
    let result = client.coupons().batch_update(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.batch_update(client, %{"resources" => %{"1" => %{"store_wide" => false, "products" => [123], "product_variants" => [1001, 1002]}}})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons batch-update --body '{"resources":{"1":{"store_wide":false,"products":[123],"product_variants":[1001,1002]}}}' --yes

```

- Method: `PATCH`

- Path: `/v1/coupons/batch`

- Full URL: `https://sell.app/api/v1/coupons/batch`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v1/coupons/batch" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": {
    "1": {
      "store_wide": false,
      "products": [
        123
      ],
      "product_variants": [
        1001,
        1002
      ]
    }
  }
}'
```

## Path Parameters
None.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 255
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": [
              "number",
              "string"
            ],
            "minimum": 1,
            "maxLength": 255,
            "description": "A decimal discount value of at least 1. Percentage discounts cannot exceed 100; amount discounts use the store currency's major unit."
          },
          "store_wide": {
            "type": "boolean"
          },
          "products": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "integer"
            },
            "description": "Product IDs the coupon applies to when store_wide is false."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Optional variant restrictions. Omit to preserve existing restrictions or send an empty array to allow every variant of the selected products."
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "A future date and time, or null for no expiry."
          },
          "minimum_amount": {
            "type": [
              "number",
              "string",
              "null"
            ],
            "minimum": 1,
            "maxLength": 255,
            "description": "A decimal minimum order amount in the store currency's major unit, or null for no minimum."
          }
        }
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": {
    "1": {
      "store_wide": false,
      "products": [
        123
      ],
      "product_variants": [
        1001,
        1002
      ]
    }
  }
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": "string"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "store_wide": {
            "type": "boolean"
          },
          "minimum_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
            "example": "2026-07-03 12:15:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "maximum_discount_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
          },
          "products": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "discount",
          "limit",
          "store_wide",
          "minimum_amount",
          "expires_at",
          "created_at",
          "updated_at",
          "store_id",
          "deleted_at",
          "maximum_discount_amount",
          "products",
          "product_variants"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "code": "BONANZA",
      "type": "PERCENTAGE",
      "discount": "80",
      "limit": null,
      "store_wide": false,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "deleted_at": null,
      "products": [
        123
      ],
      "product_variants": [
        1001,
        1002
      ],
      "maximum_discount_amount": null
    }
  ]
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## DELETE /v1/coupons/batch

Batch delete coupons

Soft-delete multiple coupons by sending their IDs in `resources`.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.batchDelete({
  "resources": [1, 2]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.batch_delete(resources=[1, 2])
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->batchDelete(resources: [1, 2]);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsBatchDeleteParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[1,2]}"), params); err != nil { panic(err) }
    if err := client.Coupons().BatchDelete(context.Background(), params); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.Coupons.BatchDeleteAsync(new CouponsBatchDeleteOptions
    {
        Resources = JsonConvert.DeserializeObject<List<long>>("[1,2]")!,
    });
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.batchDelete(resources = listOf(1L, 2L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.batch_delete(resources: [1, 2])
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::BatchDeleteParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = BatchDeleteParams::new(serde_json::from_str("{\"resources\":[1,2]}")?);
    let result = client.coupons().batch_delete(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.batch_delete(client, %{"resources" => [1, 2]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons batch-delete --body '{"resources":[1,2]}' --yes

```

- Method: `DELETE`

- Path: `/v1/coupons/batch`

- Full URL: `https://sell.app/api/v1/coupons/batch`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v1/coupons/batch" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    1,
    2
  ]
}'
```

## Path Parameters
None.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "integer"
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    1,
    2
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": "string"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "store_wide": {
            "type": "boolean"
          },
          "minimum_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
            "example": "2026-07-03 12:15:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "maximum_discount_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
          },
          "products": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "discount",
          "limit",
          "store_wide",
          "minimum_amount",
          "expires_at",
          "created_at",
          "updated_at",
          "store_id",
          "deleted_at",
          "maximum_discount_amount",
          "products",
          "product_variants"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "code": "BONANZA",
      "type": "PERCENTAGE",
      "discount": "80",
      "limit": null,
      "store_wide": true,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "deleted_at": "2026-08-30T12:00:01.000000Z",
      "products": [],
      "product_variants": [],
      "maximum_discount_amount": null
    },
    {
      "id": 2,
      "code": "BONANZA2",
      "type": "PERCENTAGE",
      "discount": "80",
      "limit": null,
      "store_wide": true,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "deleted_at": "2026-08-30T12:00:01.000000Z",
      "products": [],
      "product_variants": [],
      "maximum_discount_amount": null
    }
  ]
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/sections/search

Search sections

Search sections using JSON body filters, search terms, includes, and sort instructions.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.search({
  "filters": [{"field": "id", "operator": "=", "value": 1}],
  "sort": [{"field": "created_at", "direction": "desc"}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.search(
    filters=[{"field": "id", "operator": "=", "value": 1}],
    sort=[{"field": "created_at", "direction": "desc"}]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->search(
    filters: [['field' => 'id', 'operator' => '=', 'value' => 1]],
    sort: [['field' => 'created_at', 'direction' => 'desc']],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.SectionsSearchParams{}
    if err := json.Unmarshal([]byte("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}"), params); err != nil { panic(err) }
    page := client.Sections().Search(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Sections.SearchAsync(new SectionsSearchOptions
    {
        Filters = JsonConvert.DeserializeObject<List<SearchSectionsRequestApplicationJsonPropertyFiltersItem>>("[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}]")!,
        Sort = JsonConvert.DeserializeObject<List<SearchSectionsRequestApplicationJsonPropertySortItem>>("[{\"field\":\"created_at\",\"direction\":\"desc\"}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.search(filters = listOf(ObjectMapperFactory.read("{\"field\":\"id\",\"operator\":\"=\",\"value\":1}", app.sell.sellapp.models.SearchSectionsRequestApplicationJsonPropertyFiltersItem::class.java)), sort = listOf(ObjectMapperFactory.read("{\"field\":\"created_at\",\"direction\":\"desc\"}", app.sell.sellapp.models.SearchSectionsRequestApplicationJsonPropertySortItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.search(
  filters: [{ field: "id", operator: "=", value: 1 }],
  sort: [{ field: "created_at", direction: "desc" }]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::sections::SearchParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = SearchParams::new(serde_json::from_str("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}")?);
    let result = client.sections().search(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.search(client, %{"filters" => [%{"field" => "id", "operator" => "=", "value" => 1}], "sort" => [%{"field" => "created_at", "direction" => "desc"}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections search --body '{"filters":[{"field":"id","operator":"=","value":1}],"sort":[{"field":"created_at","direction":"desc"}]}'

```

- Method: `POST`

- Path: `/v1/sections/search`

- Full URL: `https://sell.app/api/v1/sections/search`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/sections/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "operator": {
            "type": "string",
            "default": "="
          },
          "value": {},
          "type": {
            "type": "string",
            "enum": [
              "and",
              "or"
            ],
            "default": "and"
          },
          "nested": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "anyOf": [
          {
            "required": [
              "field"
            ]
          },
          {
            "required": [
              "nested"
            ]
          }
        ]
      }
    },
    "sort": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "default": "asc"
          }
        },
        "required": [
          "field"
        ]
      }
    },
    "search": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "null"
          ]
        },
        "case_sensitive": {
          "type": "boolean"
        }
      }
    },
    "includes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "relation": {
            "type": "string"
          }
        },
        "required": [
          "relation"
        ]
      }
    }
  }
}
```

Example:

```json
{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "hidden": {
            "type": "boolean"
          },
          "order": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "groups_linked": {
            "type": "integer"
          },
          "products_linked": {
            "type": "integer"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "title": {
                  "type": "string"
                },
                "group_products": {
                  "type": "integer"
                }
              },
              "required": [
                "id",
                "title",
                "group_products"
              ]
            }
          },
          "products": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The product identifier, returned as a string by the section resource."
                },
                "title": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "title",
                "description"
              ]
            }
          }
        },
        "required": [
          "id",
          "title",
          "slug",
          "hidden",
          "order",
          "created_at",
          "updated_at",
          "store_id",
          "groups_linked",
          "products_linked",
          "groups",
          "products"
        ]
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "title": "Dissection",
      "slug": "dissection",
      "hidden": false,
      "order": 1,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "groups_linked": 1,
      "products_linked": 1,
      "groups": [
        {
          "id": 1,
          "title": "Project Planning Toolkit",
          "group_products": 1
        }
      ],
      "products": [
        {
          "id": "1",
          "title": "Project Planning Guide",
          "description": "Includes practical examples and a downloadable checklist."
        }
      ]
    }
  ],
  "links": {
    "first": "https://sell.app/api/v1/sections/search?page=1",
    "last": "https://sell.app/api/v1/sections/search?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v1/sections/search",
    "per_page": 20,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v1/sections/search?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/sections/batch

Batch create sections

Create multiple sections in one request by sending a `resources` array.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.batchCreate({
  "resources": [{"title": "Featured", "hidden": false}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.batch_create(resources=[{"title": "Featured", "hidden": False}])
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->batchCreate(resources: [['title' => 'Featured', 'hidden' => false]]);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.SectionsBatchCreateParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[{\"title\":\"Featured\",\"hidden\":false}]}"), params); err != nil { panic(err) }
    result, err := client.Sections().BatchCreate(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Sections.BatchCreateAsync(new SectionsBatchCreateOptions
    {
        Resources = JsonConvert.DeserializeObject<List<BatchCreateSectionsRequestApplicationJsonPropertyResourcesItem>>("[{\"title\":\"Featured\",\"hidden\":false}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.batchCreate(resources = listOf(ObjectMapperFactory.read("{\"title\":\"Featured\",\"hidden\":false}", app.sell.sellapp.models.BatchCreateSectionsRequestApplicationJsonPropertyResourcesItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.batch_create(resources: [{ title: "Featured", hidden: false }])
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::sections::BatchCreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = BatchCreateParams::new(serde_json::from_str("{\"resources\":[{\"title\":\"Featured\",\"hidden\":false}]}")?);
    let result = client.sections().batch_create(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.batch_create(client, %{"resources" => [%{"title" => "Featured", "hidden" => false}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections batch-create --body '{"resources":[{"title":"Featured","hidden":false}]}' --yes

```

- Method: `POST`

- Path: `/v1/sections/batch`

- Full URL: `https://sell.app/api/v1/sections/batch`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/sections/batch" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    {
      "title": "Featured",
      "hidden": false
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 255
          },
          "hidden": {
            "type": "boolean"
          }
        },
        "required": [
          "title",
          "hidden"
        ]
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    {
      "title": "Featured",
      "hidden": false
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "hidden": {
            "type": "boolean"
          },
          "order": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "groups_linked": {
            "type": "integer"
          },
          "products_linked": {
            "type": "integer"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "title": {
                  "type": "string"
                },
                "group_products": {
                  "type": "integer"
                }
              },
              "required": [
                "id",
                "title",
                "group_products"
              ]
            }
          },
          "products": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The product identifier, returned as a string by the section resource."
                },
                "title": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "title",
                "description"
              ]
            }
          }
        },
        "required": [
          "id",
          "title",
          "slug",
          "hidden",
          "order",
          "created_at",
          "updated_at",
          "store_id",
          "groups_linked",
          "products_linked",
          "groups",
          "products"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "title": "Featured",
      "slug": "featured",
      "hidden": false,
      "order": 1,
      "created_at": "2026-08-30T12:00:01.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "groups_linked": 0,
      "products_linked": 0,
      "groups": [],
      "products": []
    }
  ]
}
```

### 201

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "hidden": {
            "type": "boolean"
          },
          "order": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "groups_linked": {
            "type": "integer"
          },
          "products_linked": {
            "type": "integer"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "title": {
                  "type": "string"
                },
                "group_products": {
                  "type": "integer"
                }
              },
              "required": [
                "id",
                "title",
                "group_products"
              ]
            }
          },
          "products": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The product identifier, returned as a string by the section resource."
                },
                "title": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "title",
                "description"
              ]
            }
          }
        },
        "required": [
          "id",
          "title",
          "slug",
          "hidden",
          "order",
          "created_at",
          "updated_at",
          "store_id",
          "groups_linked",
          "products_linked",
          "groups",
          "products"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "title": "Featured",
      "slug": "featured",
      "hidden": false,
      "order": 1,
      "created_at": "2026-08-30T12:00:01.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "groups_linked": 0,
      "products_linked": 0,
      "groups": [],
      "products": []
    }
  ]
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v1/sections/batch

Batch update sections

Update multiple sections in one request by sending a `resources` object keyed by section ID.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.batchUpdate({
  "resources": {"1": {"title":"Featured","hidden":false}}
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.batch_update(resources={"1": {"title": "Featured", "hidden": False}})
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->batchUpdate(resources: ['1' => ['title' => 'Featured', 'hidden' => false]]);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.SectionsBatchUpdateParams{}
    if err := json.Unmarshal([]byte("{\"resources\":{\"1\":{\"title\":\"Featured\",\"hidden\":false}}}"), params); err != nil { panic(err) }
    result, err := client.Sections().BatchUpdate(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Sections.BatchUpdateAsync(new SectionsBatchUpdateOptions
    {
        Resources = JsonConvert.DeserializeObject<BatchUpdateSectionsRequestApplicationJsonPropertyResources>("{\"1\":{\"title\":\"Featured\",\"hidden\":false}}")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.batchUpdate(resources = ObjectMapperFactory.read("{\"1\":{\"title\":\"Featured\",\"hidden\":false}}", app.sell.sellapp.models.BatchUpdateSectionsRequestApplicationJsonPropertyResources::class.java))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.batch_update(resources: { "1" => { title: "Featured", hidden: false } })
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::sections::BatchUpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = BatchUpdateParams::new(serde_json::from_str("{\"resources\":{\"1\":{\"title\":\"Featured\",\"hidden\":false}}}")?);
    let result = client.sections().batch_update(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.batch_update(client, %{"resources" => %{"1" => %{"title" => "Featured", "hidden" => false}}})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections batch-update --body '{"resources":{"1":{"title":"Featured","hidden":false}}}' --yes

```

- Method: `PATCH`

- Path: `/v1/sections/batch`

- Full URL: `https://sell.app/api/v1/sections/batch`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v1/sections/batch" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": {
    "1": {
      "title": "Featured",
      "hidden": false
    }
  }
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 255
          },
          "hidden": {
            "type": "boolean"
          }
        }
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": {
    "1": {
      "title": "Featured",
      "hidden": false
    }
  }
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "hidden": {
            "type": "boolean"
          },
          "order": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "groups_linked": {
            "type": "integer"
          },
          "products_linked": {
            "type": "integer"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "title": {
                  "type": "string"
                },
                "group_products": {
                  "type": "integer"
                }
              },
              "required": [
                "id",
                "title",
                "group_products"
              ]
            }
          },
          "products": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The product identifier, returned as a string by the section resource."
                },
                "title": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "title",
                "description"
              ]
            }
          }
        },
        "required": [
          "id",
          "title",
          "slug",
          "hidden",
          "order",
          "created_at",
          "updated_at",
          "store_id",
          "groups_linked",
          "products_linked",
          "groups",
          "products"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "title": "Featured",
      "slug": "dissection",
      "hidden": false,
      "order": 1,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "groups_linked": 1,
      "products_linked": 1,
      "groups": [
        {
          "id": 1,
          "title": "Project Planning Toolkit",
          "group_products": 1
        }
      ],
      "products": [
        {
          "id": "1",
          "title": "Project Planning Guide",
          "description": "Includes practical examples and a downloadable checklist."
        }
      ]
    }
  ]
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## DELETE /v1/sections/batch

Batch delete sections

Delete multiple sections in one request by sending the section IDs in `resources`.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.sections.batchDelete({
  "resources": [1, 2]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.sections.batch_delete(resources=[1, 2])
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->sections()->batchDelete(resources: [1, 2]);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.SectionsBatchDeleteParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[1,2]}"), params); err != nil { panic(err) }
    if err := client.Sections().BatchDelete(context.Background(), params); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.Sections.BatchDeleteAsync(new SectionsBatchDeleteOptions
    {
        Resources = JsonConvert.DeserializeObject<List<long>>("[1,2]")!,
    });
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.sections.batchDelete(resources = listOf(1L, 2L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.sections.batch_delete(resources: [1, 2])
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::sections::BatchDeleteParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = BatchDeleteParams::new(serde_json::from_str("{\"resources\":[1,2]}")?);
    let result = client.sections().batch_delete(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Sections.batch_delete(client, %{"resources" => [1, 2]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp sections batch-delete --body '{"resources":[1,2]}' --yes

```

- Method: `DELETE`

- Path: `/v1/sections/batch`

- Full URL: `https://sell.app/api/v1/sections/batch`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v1/sections/batch" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    1,
    2
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "integer"
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    1,
    2
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "hidden": {
            "type": "boolean"
          },
          "order": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "groups_linked": {
            "type": "integer"
          },
          "products_linked": {
            "type": "integer"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "title": {
                  "type": "string"
                },
                "group_products": {
                  "type": "integer"
                }
              },
              "required": [
                "id",
                "title",
                "group_products"
              ]
            }
          },
          "products": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The product identifier, returned as a string by the section resource."
                },
                "title": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "title",
                "description"
              ]
            }
          }
        },
        "required": [
          "id",
          "title",
          "slug",
          "hidden",
          "order",
          "created_at",
          "updated_at",
          "store_id",
          "groups_linked",
          "products_linked",
          "groups",
          "products"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "title": "Dissection",
      "slug": "dissection",
      "hidden": false,
      "order": 1,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "groups_linked": 1,
      "products_linked": 1,
      "groups": [
        {
          "id": 1,
          "title": "Project Planning Toolkit",
          "group_products": 1
        }
      ],
      "products": [
        {
          "id": "1",
          "title": "Project Planning Guide",
          "description": "Includes practical examples and a downloadable checklist."
        }
      ],
      "deleted_at": "2026-08-30T12:00:01.000000Z"
    },
    {
      "id": 2,
      "title": "Dissection",
      "slug": "dissection-2",
      "hidden": false,
      "order": 1,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "groups_linked": 1,
      "products_linked": 1,
      "groups": [
        {
          "id": 1,
          "title": "Project Planning Toolkit",
          "group_products": 1
        }
      ],
      "products": [
        {
          "id": "1",
          "title": "Project Planning Guide",
          "description": "Includes practical examples and a downloadable checklist."
        }
      ],
      "deleted_at": "2026-08-30T12:00:01.000000Z"
    }
  ]
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/listings

List legacy V1 listings

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `GET`

- Path: `/v1/listings`

- Full URL: `https://sell.app/api/v1/listings`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/listings" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/listings

Create legacy V1 listing

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `POST`

- Path: `/v1/listings`

- Full URL: `https://sell.app/api/v1/listings`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/listings" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/listings/search

Search legacy V1 listings

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `POST`

- Path: `/v1/listings/search`

- Full URL: `https://sell.app/api/v1/listings/search`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/listings/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/listings/batch

Batch create legacy V1 listings

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `POST`

- Path: `/v1/listings/batch`

- Full URL: `https://sell.app/api/v1/listings/batch`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/listings/batch" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v1/listings/batch

Batch update legacy V1 listings

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `PATCH`

- Path: `/v1/listings/batch`

- Full URL: `https://sell.app/api/v1/listings/batch`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v1/listings/batch" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## DELETE /v1/listings/batch

Batch delete legacy V1 listings

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `DELETE`

- Path: `/v1/listings/batch`

- Full URL: `https://sell.app/api/v1/listings/batch`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v1/listings/batch" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/listings/{listing}

Retrieve legacy V1 listing

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `GET`

- Path: `/v1/listings/{listing}`

- Full URL: `https://sell.app/api/v1/listings/{listing}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_LISTING_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/listings/${SELLAPP_LISTING_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `listing` (`integer`, required): The listing path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v1/listings/{listing}

Update legacy V1 listing

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `PATCH`

- Path: `/v1/listings/{listing}`

- Full URL: `https://sell.app/api/v1/listings/{listing}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_LISTING_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v1/listings/${SELLAPP_LISTING_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `listing` (`integer`, required): The listing path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## DELETE /v1/listings/{listing}

Delete legacy V1 listing

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `DELETE`

- Path: `/v1/listings/{listing}`

- Full URL: `https://sell.app/api/v1/listings/{listing}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_LISTING_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v1/listings/${SELLAPP_LISTING_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `listing` (`integer`, required): The listing path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/invoices

List legacy V1 invoices

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `GET`

- Path: `/v1/invoices`

- Full URL: `https://sell.app/api/v1/invoices`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/invoices" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/invoices

Create legacy V1 invoice

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `POST`

- Path: `/v1/invoices`

- Full URL: `https://sell.app/api/v1/invoices`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/invoices" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/invoices/search

Search legacy V1 invoices

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `POST`

- Path: `/v1/invoices/search`

- Full URL: `https://sell.app/api/v1/invoices/search`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/invoices/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v1/invoices/{invoice}

Retrieve legacy V1 invoice

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `GET`

- Path: `/v1/invoices/{invoice}`

- Full URL: `https://sell.app/api/v1/invoices/{invoice}`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_INVOICE_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v1/invoices/${SELLAPP_INVOICE_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `invoice` (`integer`, required): The invoice path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v1/invoices/{invoice}/checkout

Create legacy V1 invoice checkout

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `POST`

- Path: `/v1/invoices/{invoice}/checkout`

- Full URL: `https://sell.app/api/v1/invoices/{invoice}/checkout`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_INVOICE_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v1/invoices/${SELLAPP_INVOICE_ID}/checkout" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `invoice` (`integer`, required): The invoice path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v1/invoices/{invoice}/issue-replacement

Issue legacy V1 invoice replacement

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `PATCH`

- Path: `/v1/invoices/{invoice}/issue-replacement`

- Full URL: `https://sell.app/api/v1/invoices/{invoice}/issue-replacement`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_INVOICE_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v1/invoices/${SELLAPP_INVOICE_ID}/issue-replacement" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `invoice` (`integer`, required): The invoice path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v1/invoices/{invoice}/mark-completed

Mark legacy V1 invoice completed

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `PATCH`

- Path: `/v1/invoices/{invoice}/mark-completed`

- Full URL: `https://sell.app/api/v1/invoices/{invoice}/mark-completed`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_INVOICE_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v1/invoices/${SELLAPP_INVOICE_ID}/mark-completed" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `invoice` (`integer`, required): The invoice path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v1/invoices/{invoice}/mark-voided

Mark legacy V1 invoice voided

This legacy V1 endpoint now returns `410 Gone`. Use the corresponding V2 endpoint instead.

Deprecated operation. Review the replacement and compatibility notes before integrating.

- Method: `PATCH`

- Path: `/v1/invoices/{invoice}/mark-voided`

- Full URL: `https://sell.app/api/v1/invoices/{invoice}/mark-voided`

- Authentication: `Authorization: Bearer <credential>` header required AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_INVOICE_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v1/invoices/${SELLAPP_INVOICE_ID}/mark-voided" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `invoice` (`integer`, required): The invoice path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `X-STORE` (`string`, required): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 410

This legacy endpoint is no longer available.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  },
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ]
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "endpoint_gone",
  "message": "This endpoint is not available anymore. Please use the /api/v2 endpoints.",
  "status": 410,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#endpoint-gone"
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Create an add-on draft (/docs/api/add-ons/create-an-add-on-draft)

## POST /v2/addons

Create an add-on draft

Create an add-on as a draft. The response may contain zero variants by design. Create its one published, fixed-price, single-payment variant through the existing product variant endpoint, then publish the add-on with PATCH `/v2/addons/{addon}`. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.addOns.create({
  "title": "Customer support",
  "description": "Priority support for launches scheduled suspiciously close to Friday.",
  "visibility": "PUBLIC",
  "parentProductIds": [120, 121]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.add_ons.create(
    title="Customer support",
    description="Priority support for launches scheduled suspiciously close to Friday.",
    visibility="PUBLIC",
    parent_product_ids=[120, 121]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->addOns()->create(
    title: 'Customer support',
    description: 'Priority support for launches scheduled suspiciously close to Friday.',
    visibility: 'PUBLIC',
    parentProductIds: [120, 121],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AddOnsCreateParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Customer support\",\"description\":\"Priority support for launches scheduled suspiciously close to Friday.\",\"visibility\":\"PUBLIC\",\"parent_product_ids\":[120,121]}"), params); err != nil { panic(err) }
    result, err := client.AddOns().Create(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AddOns.CreateAsync(new AddOnsCreateOptions
    {
        Title = "Customer support",
        Description = "Priority support for launches scheduled suspiciously close to Friday.",
        Visibility = JsonConvert.DeserializeObject<CatalogVisibility>("\"PUBLIC\"")!,
        ParentProductIds = JsonConvert.DeserializeObject<List<long>>("[120,121]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.addOns.create(title = "Customer support", description = "Priority support for launches scheduled suspiciously close to Friday.", visibility = app.sell.sellapp.types.CatalogVisibility("PUBLIC"), parentProductIds = listOf(120L, 121L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.add_ons.create(
  title: "Customer support",
  description: "Priority support for launches scheduled suspiciously close to Friday.",
  visibility: "PUBLIC",
  parent_product_ids: [120, 121]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::add_ons::CreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateParams::new(serde_json::from_str("{\"title\":\"Customer support\",\"description\":\"Priority support for launches scheduled suspiciously close to Friday.\",\"visibility\":\"PUBLIC\",\"parent_product_ids\":[120,121]}")?);
    let result = client.add_ons().create(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AddOns.create(client, %{"title" => "Customer support", "description" => "Priority support for launches scheduled suspiciously close to Friday.", "visibility" => "PUBLIC", "parent_product_ids" => [120, 121]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp add-ons create --body '{"title":"Customer support","description":"Priority support for launches scheduled suspiciously close to Friday.","visibility":"PUBLIC","parent_product_ids":[120,121]}' --yes

```

- Method: `POST`

- Path: `/v2/addons`

- Full URL: `https://sell.app/api/v2/addons`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/addons" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Customer support",
  "description": "Priority support for launches scheduled suspiciously close to Friday.",
  "visibility": "PUBLIC",
  "parent_product_ids": [
    120,
    121
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255,
      "description": "Seller-facing title for the add-on."
    },
    "slug": {
      "type": "string",
      "maxLength": 255,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "description": "Optional store-unique slug. When omitted during creation, SellApp generates one from the title."
    },
    "description": {
      "type": "string",
      "minLength": 5,
      "maxLength": 5000,
      "description": "Description shown when the add-on is offered."
    },
    "visibility": {
      "type": "string",
      "enum": [
        "PUBLIC",
        "ON_HOLD",
        "HIDDEN",
        "PRIVATE"
      ]
    },
    "is_draft": {
      "type": "boolean",
      "description": "New add-ons are always drafts. Set this to false only after creating exactly one published, fixed-price, single-payment variant through `/v2/products/{addon}/variants`."
    },
    "parent_product_ids": {
      "type": "array",
      "uniqueItems": true,
      "description": "Ordered IDs of same-store, non-subscription products, courses, or bookings to assign. Supplying the field replaces the complete assignment set.",
      "items": {
        "type": "integer"
      }
    }
  },
  "required": [
    "title",
    "description",
    "visibility"
  ]
}
```

Example:

```json
{
  "title": "Customer support",
  "description": "Priority support for launches scheduled suspiciously close to Friday.",
  "visibility": "PUBLIC",
  "parent_product_ids": [
    120,
    121
  ]
}
```

## Responses

### 201

Add-on draft created.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
      "properties": {
        "id": {
          "type": "integer",
          "example": 410
        },
        "store_id": {
          "type": "integer",
          "example": 12
        },
        "title": {
          "type": "string",
          "example": "Customer support"
        },
        "slug": {
          "type": "string",
          "example": "customer-support"
        },
        "description": {
          "type": "string",
          "example": "Priority support for launches scheduled suspiciously close to Friday."
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ],
          "example": "PUBLIC"
        },
        "type": {
          "type": "string",
          "enum": [
            "addon"
          ],
          "example": "addon"
        },
        "is_draft": {
          "type": "boolean",
          "example": true
        },
        "is_discoverable": {
          "type": "boolean",
          "example": false
        },
        "parent_product_ids": {
          "type": "array",
          "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
          "items": {
            "type": "integer"
          },
          "example": [
            120,
            121
          ]
        },
        "variants": {
          "type": "array",
          "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
          "items": {
            "type": "object",
            "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
            "properties": {
              "id": {
                "type": "integer",
                "example": 8801
              },
              "title": {
                "type": "string",
                "example": "Default"
              },
              "is_draft": {
                "type": "boolean",
                "example": false
              }
            },
            "required": [
              "id",
              "title",
              "is_draft"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "store_id",
        "title",
        "slug",
        "description",
        "visibility",
        "type",
        "is_draft",
        "is_discoverable",
        "parent_product_ids",
        "variants",
        "created_at",
        "updated_at",
        "deleted_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 410,
    "store_id": 12,
    "title": "Customer support",
    "slug": "customer-support",
    "description": "Priority support for launches scheduled suspiciously close to Friday.",
    "visibility": "PUBLIC",
    "type": "addon",
    "is_draft": true,
    "is_discoverable": false,
    "parent_product_ids": [
      120,
      121
    ],
    "variants": [],
    "created_at": "2026-07-11T12:00:00.000000Z",
    "updated_at": "2026-07-11T12:00:00.000000Z",
    "deleted_at": null,
    "delivery_text": ""
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Delete an add-on (/docs/api/add-ons/delete-an-add-on)

## DELETE /v2/addons/{addon}

Delete an add-on

Soft-delete an add-on and remove its product assignments. The deleted resource is returned for audit and reconciliation workflows. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.addOns.delete({
  "addon": 410
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.add_ons.delete(addon=410)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->addOns()->delete(addon: 410);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    if err := client.AddOns().Delete(context.Background(), 410); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.AddOns.DeleteAsync("410");
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.addOns.delete(addon = "410")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.add_ons.delete(addon: 410)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::add_ons::DeleteParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = DeleteParams::default();
    let result = client.add_ons().delete("410", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AddOns.delete(client, 410)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp add-ons delete 410 --yes

```

- Method: `DELETE`

- Path: `/v2/addons/{addon}`

- Full URL: `https://sell.app/api/v2/addons/{addon}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_ADDON_ID='410'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v2/addons/${SELLAPP_ADDON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `addon` (`integer`, required): The addon path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
      "properties": {
        "id": {
          "type": "integer",
          "example": 410
        },
        "store_id": {
          "type": "integer",
          "example": 12
        },
        "title": {
          "type": "string",
          "example": "Customer support"
        },
        "slug": {
          "type": "string",
          "example": "customer-support"
        },
        "description": {
          "type": "string",
          "example": "Priority support for launches scheduled suspiciously close to Friday."
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ],
          "example": "PUBLIC"
        },
        "type": {
          "type": "string",
          "enum": [
            "addon"
          ],
          "example": "addon"
        },
        "is_draft": {
          "type": "boolean",
          "example": true
        },
        "is_discoverable": {
          "type": "boolean",
          "example": false
        },
        "parent_product_ids": {
          "type": "array",
          "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
          "items": {
            "type": "integer"
          },
          "example": [
            120,
            121
          ]
        },
        "variants": {
          "type": "array",
          "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
          "items": {
            "type": "object",
            "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
            "properties": {
              "id": {
                "type": "integer",
                "example": 8801
              },
              "title": {
                "type": "string",
                "example": "Default"
              },
              "is_draft": {
                "type": "boolean",
                "example": false
              }
            },
            "required": [
              "id",
              "title",
              "is_draft"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "store_id",
        "title",
        "slug",
        "description",
        "visibility",
        "type",
        "is_draft",
        "is_discoverable",
        "parent_product_ids",
        "variants",
        "created_at",
        "updated_at",
        "deleted_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 410,
    "store_id": 12,
    "title": "Customer support",
    "slug": "customer-support",
    "description": "Priority support for launches scheduled suspiciously close to Friday.",
    "visibility": "PUBLIC",
    "type": "addon",
    "is_draft": true,
    "is_discoverable": false,
    "parent_product_ids": [
      120,
      121
    ],
    "variants": [],
    "created_at": "2026-07-11T12:00:00.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "deleted_at": "2026-08-30T12:00:01.000000Z",
    "delivery_text": ""
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Overview (/docs/api/add-ons)



Add-ons are optional extras offered at checkout. Assign them to the products, courses, or bookings that should offer them.

New add-ons are always created as drafts and can initially have no variants. Create exactly one published, fixed-price, single-payment variant through the [product variant endpoints](/api/product-variants), then publish the add-on by setting `is_draft` to `false`.

When replacing an add-on's parent products or a product's add-ons, send the whole list of IDs in the order you want, not just the changes. Every referenced resource must belong to the selected store. Subscription products cannot offer or participate in add-on relationships.

## Endpoints [#endpoints]

* [List add-ons](/api/add-ons/list-add-ons)
* [Search add-ons](/api/add-ons/search-add-ons)
* [Create an add-on draft](/api/add-ons/create-an-add-on-draft)
* [Retrieve an add-on](/api/add-ons/retrieve-an-add-on)
* [Update an add-on](/api/add-ons/update-an-add-on)
* [Replace an add-on](/api/add-ons/replace-an-add-on)
* [Delete an add-on](/api/add-ons/delete-an-add-on)
* [List an add-on's parent products](/api/add-ons/list-parent-products)
* [Replace an add-on's parent products](/api/add-ons/replace-parent-products)
* [List a product's add-ons](/api/add-ons/list-product-add-ons)
* [Replace a product's add-ons](/api/add-ons/replace-product-add-ons)


# List add-ons (/docs/api/add-ons/list-add-ons)

## GET /v2/addons

List add-ons

Retrieve the store's add-ons with compact variant references and ordered parent-product assignments. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.addOns.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.add_ons.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->addOns()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AddOnsListParams{}
    page := client.AddOns().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AddOns.ListAsync(new AddOnsListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.addOns.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.add_ons.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::add_ons::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.add_ons().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AddOns.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp add-ons list

```

- Method: `GET`

- Path: `/v2/addons`

- Full URL: `https://sell.app/api/v2/addons`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/addons" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching items in one data array without pagination links or metadata.
- `with_drafts` (`boolean`, optional): Include draft add-ons alongside published add-ons.
- `only_drafts` (`boolean`, optional): Return only draft add-ons.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
            "properties": {
              "id": {
                "type": "integer",
                "example": 410
              },
              "store_id": {
                "type": "integer",
                "example": 12
              },
              "title": {
                "type": "string",
                "example": "Customer support"
              },
              "slug": {
                "type": "string",
                "example": "customer-support"
              },
              "description": {
                "type": "string",
                "example": "Priority support for launches scheduled suspiciously close to Friday."
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ],
                "example": "PUBLIC"
              },
              "type": {
                "type": "string",
                "enum": [
                  "addon"
                ],
                "example": "addon"
              },
              "is_draft": {
                "type": "boolean",
                "example": true
              },
              "is_discoverable": {
                "type": "boolean",
                "example": false
              },
              "parent_product_ids": {
                "type": "array",
                "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
                "items": {
                  "type": "integer"
                },
                "example": [
                  120,
                  121
                ]
              },
              "variants": {
                "type": "array",
                "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
                "items": {
                  "type": "object",
                  "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
                  "properties": {
                    "id": {
                      "type": "integer",
                      "example": 8801
                    },
                    "title": {
                      "type": "string",
                      "example": "Default"
                    },
                    "is_draft": {
                      "type": "boolean",
                      "example": false
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "is_draft"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "store_id",
              "title",
              "slug",
              "description",
              "visibility",
              "type",
              "is_draft",
              "is_discoverable",
              "parent_product_ids",
              "variants",
              "created_at",
              "updated_at",
              "deleted_at"
            ]
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
            "properties": {
              "id": {
                "type": "integer",
                "example": 410
              },
              "store_id": {
                "type": "integer",
                "example": 12
              },
              "title": {
                "type": "string",
                "example": "Customer support"
              },
              "slug": {
                "type": "string",
                "example": "customer-support"
              },
              "description": {
                "type": "string",
                "example": "Priority support for launches scheduled suspiciously close to Friday."
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ],
                "example": "PUBLIC"
              },
              "type": {
                "type": "string",
                "enum": [
                  "addon"
                ],
                "example": "addon"
              },
              "is_draft": {
                "type": "boolean",
                "example": true
              },
              "is_discoverable": {
                "type": "boolean",
                "example": false
              },
              "parent_product_ids": {
                "type": "array",
                "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
                "items": {
                  "type": "integer"
                },
                "example": [
                  120,
                  121
                ]
              },
              "variants": {
                "type": "array",
                "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
                "items": {
                  "type": "object",
                  "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
                  "properties": {
                    "id": {
                      "type": "integer",
                      "example": 8801
                    },
                    "title": {
                      "type": "string",
                      "example": "Default"
                    },
                    "is_draft": {
                      "type": "boolean",
                      "example": false
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "is_draft"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "store_id",
              "title",
              "slug",
              "description",
              "visibility",
              "type",
              "is_draft",
              "is_discoverable",
              "parent_product_ids",
              "variants",
              "created_at",
              "updated_at",
              "deleted_at"
            ]
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 410,
      "store_id": 12,
      "title": "Customer support",
      "slug": "customer-support",
      "description": "Priority support for launches scheduled suspiciously close to Friday.",
      "visibility": "PUBLIC",
      "type": "addon",
      "is_draft": true,
      "is_discoverable": false,
      "parent_product_ids": [
        120,
        121
      ],
      "variants": [],
      "created_at": "2026-07-11T12:00:00.000000Z",
      "updated_at": "2026-07-11T12:00:00.000000Z",
      "deleted_at": null,
      "delivery_text": ""
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/addons?page=1",
    "last": "https://sell.app/api/v2/addons?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/addons",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/addons?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# List parent products (/docs/api/add-ons/list-parent-products)

## GET /v2/addons/{addon}/parent-products

List an add-on's parent products

Retrieve the ordered products, courses, and bookings that currently offer this add-on. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.addOnsParentProducts.list({
  "addon": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.add_ons_parent_products.list(addon=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->addOnsParentProducts()->list(addon: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AddOnsParentProductsListParams{}
    page := client.AddOnsParentProducts().List(context.Background(), 1, params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AddOnsParentProducts.ListAsync(
    "1",
    new AddOnsParentProductsListOptions
    {
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.addOnsParentProducts.list(addon = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.add_ons_parent_products.list(addon: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::add_ons_parent_products::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.add_ons_parent_products().list("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AddOnsParentProducts.list(client, 1, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp add-ons parent-products list 1

```

- Method: `GET`

- Path: `/v2/addons/{addon}/parent-products`

- Full URL: `https://sell.app/api/v2/addons/{addon}/parent-products`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_ADDON_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/addons/${SELLAPP_ADDON_ID}/parent-products" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `addon` (`integer`, required): The addon path parameter.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching items in one data array without pagination links or metadata.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer",
                "example": 120
              },
              "title": {
                "type": "string",
                "example": "Design kit"
              },
              "slug": {
                "type": "string",
                "example": "design-kit"
              },
              "type": {
                "type": "string",
                "enum": [
                  "product",
                  "course",
                  "booking"
                ],
                "example": "product"
              },
              "is_draft": {
                "type": "boolean",
                "example": false
              }
            },
            "required": [
              "id",
              "title",
              "slug",
              "type",
              "is_draft"
            ]
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer",
                "example": 120
              },
              "title": {
                "type": "string",
                "example": "Design kit"
              },
              "slug": {
                "type": "string",
                "example": "design-kit"
              },
              "type": {
                "type": "string",
                "enum": [
                  "product",
                  "course",
                  "booking"
                ],
                "example": "product"
              },
              "is_draft": {
                "type": "boolean",
                "example": false
              }
            },
            "required": [
              "id",
              "title",
              "slug",
              "type",
              "is_draft"
            ]
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example:

```json
{
  "data": [],
  "links": {
    "first": "https://sell.app/api/v2/addons/1/parent-products?page=1",
    "last": "https://sell.app/api/v2/addons/1/parent-products?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": null,
    "last_page": 1,
    "path": "https://sell.app/api/v2/addons/1/parent-products",
    "per_page": 15,
    "to": null,
    "total": 0,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/addons/1/parent-products?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# List product add-ons (/docs/api/add-ons/list-product-add-ons)

## GET /v2/products/{product}/addons

List a product's add-ons

Retrieve the ordered add-ons assigned to a product, course, or booking. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.productsAddons.list({
  "product": 120
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.products_addons.list(product=120)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->productsAddons()->list(product: 120);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.ProductsAddonsListParams{}
    page := client.ProductsAddons().List(context.Background(), 120, params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.ProductsAddons.ListAsync(
    "120",
    new ProductsAddonsListOptions
    {
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.productsAddons.list(product = "120")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.products_addons.list(product: 120)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::products_addons::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.products_addons().list("120", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.ProductsAddons.list(client, 120, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp products addons list 120

```

- Method: `GET`

- Path: `/v2/products/{product}/addons`

- Full URL: `https://sell.app/api/v2/products/{product}/addons`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_ID='120'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/products/${SELLAPP_PRODUCT_ID}/addons" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `product` (`integer`, required): The product path parameter.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching items in one data array without pagination links or metadata.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
            "properties": {
              "id": {
                "type": "integer",
                "example": 410
              },
              "store_id": {
                "type": "integer",
                "example": 12
              },
              "title": {
                "type": "string",
                "example": "Customer support"
              },
              "slug": {
                "type": "string",
                "example": "customer-support"
              },
              "description": {
                "type": "string",
                "example": "Priority support for launches scheduled suspiciously close to Friday."
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ],
                "example": "PUBLIC"
              },
              "type": {
                "type": "string",
                "enum": [
                  "addon"
                ],
                "example": "addon"
              },
              "is_draft": {
                "type": "boolean",
                "example": true
              },
              "is_discoverable": {
                "type": "boolean",
                "example": false
              },
              "parent_product_ids": {
                "type": "array",
                "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
                "items": {
                  "type": "integer"
                },
                "example": [
                  120,
                  121
                ]
              },
              "variants": {
                "type": "array",
                "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
                "items": {
                  "type": "object",
                  "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
                  "properties": {
                    "id": {
                      "type": "integer",
                      "example": 8801
                    },
                    "title": {
                      "type": "string",
                      "example": "Default"
                    },
                    "is_draft": {
                      "type": "boolean",
                      "example": false
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "is_draft"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "store_id",
              "title",
              "slug",
              "description",
              "visibility",
              "type",
              "is_draft",
              "is_discoverable",
              "parent_product_ids",
              "variants",
              "created_at",
              "updated_at",
              "deleted_at"
            ]
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
            "properties": {
              "id": {
                "type": "integer",
                "example": 410
              },
              "store_id": {
                "type": "integer",
                "example": 12
              },
              "title": {
                "type": "string",
                "example": "Customer support"
              },
              "slug": {
                "type": "string",
                "example": "customer-support"
              },
              "description": {
                "type": "string",
                "example": "Priority support for launches scheduled suspiciously close to Friday."
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ],
                "example": "PUBLIC"
              },
              "type": {
                "type": "string",
                "enum": [
                  "addon"
                ],
                "example": "addon"
              },
              "is_draft": {
                "type": "boolean",
                "example": true
              },
              "is_discoverable": {
                "type": "boolean",
                "example": false
              },
              "parent_product_ids": {
                "type": "array",
                "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
                "items": {
                  "type": "integer"
                },
                "example": [
                  120,
                  121
                ]
              },
              "variants": {
                "type": "array",
                "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
                "items": {
                  "type": "object",
                  "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
                  "properties": {
                    "id": {
                      "type": "integer",
                      "example": 8801
                    },
                    "title": {
                      "type": "string",
                      "example": "Default"
                    },
                    "is_draft": {
                      "type": "boolean",
                      "example": false
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "is_draft"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "store_id",
              "title",
              "slug",
              "description",
              "visibility",
              "type",
              "is_draft",
              "is_discoverable",
              "parent_product_ids",
              "variants",
              "created_at",
              "updated_at",
              "deleted_at"
            ]
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 410,
      "store_id": 12,
      "title": "Customer support",
      "slug": "customer-support",
      "description": "Priority support for launches scheduled suspiciously close to Friday.",
      "visibility": "PUBLIC",
      "type": "addon",
      "is_draft": true,
      "is_discoverable": false,
      "parent_product_ids": [
        120,
        121
      ],
      "variants": [],
      "created_at": "2026-07-11T12:00:00.000000Z",
      "updated_at": "2026-07-11T12:00:00.000000Z",
      "deleted_at": null,
      "delivery_text": ""
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/products/120/addons?page=1",
    "last": "https://sell.app/api/v2/products/120/addons?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/products/120/addons",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/products/120/addons?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Replace an add-on (/docs/api/add-ons/replace-an-add-on)

## PUT /v2/addons/{addon}

Update an add-on

Update an add-on and optionally replace its ordered parent-product assignments. Publication is rejected unless the add-on has exactly one published, fixed-price, single-payment variant. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.addOns.replace({
  "addon": 410,
  "description": "Priority email, chat, and launch-day reassurance.",
  "isDraft": false
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.add_ons.replace(
    addon=410,
    description="Priority email, chat, and launch-day reassurance.",
    is_draft=False
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->addOns()->replace(
    addon: 410,
    description: 'Priority email, chat, and launch-day reassurance.',
    isDraft: false,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AddOnsReplaceParams{}
    if err := json.Unmarshal([]byte("{\"description\":\"Priority email, chat, and launch-day reassurance.\",\"is_draft\":false}"), params); err != nil { panic(err) }
    result, err := client.AddOns().Replace(context.Background(), 410, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AddOns.ReplaceAsync(
    "410",
    new AddOnsReplaceOptions
    {
        Description = "Priority email, chat, and launch-day reassurance.",
        IsDraft = false,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.addOns.replace(addon = "410", description = "Priority email, chat, and launch-day reassurance.", isDraft = false)
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.add_ons.replace(
  addon: 410,
  description: "Priority email, chat, and launch-day reassurance.",
  is_draft: false
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::add_ons::ReplaceParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceParams::new(serde_json::from_str("{\"description\":\"Priority email, chat, and launch-day reassurance.\",\"is_draft\":false}")?);
    let result = client.add_ons().replace("410", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AddOns.replace(client, 410, %{"description" => "Priority email, chat, and launch-day reassurance.", "is_draft" => false})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp add-ons replace 410 --description 'Priority email, chat, and launch-day reassurance.' --is-draft false --yes

```

- Method: `PUT`

- Path: `/v2/addons/{addon}`

- Full URL: `https://sell.app/api/v2/addons/{addon}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_ADDON_ID='410'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/addons/${SELLAPP_ADDON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "description": "Priority email, chat, and launch-day reassurance.",
  "is_draft": false
}'
```

## Path Parameters
- `addon` (`integer`, required): The addon path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255,
      "description": "Seller-facing title for the add-on."
    },
    "slug": {
      "type": "string",
      "maxLength": 255,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "description": "Optional store-unique slug. When omitted during creation, SellApp generates one from the title."
    },
    "description": {
      "type": "string",
      "minLength": 5,
      "maxLength": 5000,
      "description": "Description shown when the add-on is offered."
    },
    "visibility": {
      "type": "string",
      "enum": [
        "PUBLIC",
        "ON_HOLD",
        "HIDDEN",
        "PRIVATE"
      ]
    },
    "is_draft": {
      "type": "boolean",
      "description": "New add-ons are always drafts. Set this to false only after creating exactly one published, fixed-price, single-payment variant through `/v2/products/{addon}/variants`."
    },
    "parent_product_ids": {
      "type": "array",
      "uniqueItems": true,
      "description": "Ordered IDs of same-store, non-subscription products, courses, or bookings to assign. Supplying the field replaces the complete assignment set.",
      "items": {
        "type": "integer"
      }
    }
  }
}
```

Example:

```json
{
  "description": "Priority email, chat, and launch-day reassurance.",
  "is_draft": false
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
      "properties": {
        "id": {
          "type": "integer",
          "example": 410
        },
        "store_id": {
          "type": "integer",
          "example": 12
        },
        "title": {
          "type": "string",
          "example": "Customer support"
        },
        "slug": {
          "type": "string",
          "example": "customer-support"
        },
        "description": {
          "type": "string",
          "example": "Priority support for launches scheduled suspiciously close to Friday."
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ],
          "example": "PUBLIC"
        },
        "type": {
          "type": "string",
          "enum": [
            "addon"
          ],
          "example": "addon"
        },
        "is_draft": {
          "type": "boolean",
          "example": true
        },
        "is_discoverable": {
          "type": "boolean",
          "example": false
        },
        "parent_product_ids": {
          "type": "array",
          "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
          "items": {
            "type": "integer"
          },
          "example": [
            120,
            121
          ]
        },
        "variants": {
          "type": "array",
          "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
          "items": {
            "type": "object",
            "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
            "properties": {
              "id": {
                "type": "integer",
                "example": 8801
              },
              "title": {
                "type": "string",
                "example": "Default"
              },
              "is_draft": {
                "type": "boolean",
                "example": false
              }
            },
            "required": [
              "id",
              "title",
              "is_draft"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "store_id",
        "title",
        "slug",
        "description",
        "visibility",
        "type",
        "is_draft",
        "is_discoverable",
        "parent_product_ids",
        "variants",
        "created_at",
        "updated_at",
        "deleted_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 410,
    "store_id": 12,
    "title": "Customer support",
    "slug": "customer-support",
    "description": "Priority email, chat, and launch-day reassurance.",
    "visibility": "PUBLIC",
    "type": "addon",
    "is_draft": false,
    "is_discoverable": true,
    "parent_product_ids": [
      120,
      121
    ],
    "variants": [],
    "created_at": "2026-07-11T12:00:00.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "deleted_at": null,
    "delivery_text": ""
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Replace parent products (/docs/api/add-ons/replace-parent-products)

## PUT /v2/addons/{addon}/parent-products

Replace an add-on's parent products

Replace the complete ordered parent-product assignment. IDs must belong to the same store and may reference non-subscription products, courses, or bookings. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.addOnsParentProducts.replace({
  "addon": 410,
  "resources": [121, 120]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.add_ons_parent_products.replace(
    addon=410,
    resources=[121, 120]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->addOnsParentProducts()->replace(
    addon: 410,
    resources: [121, 120],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AddOnsParentProductsReplaceParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[121,120]}"), params); err != nil { panic(err) }
    result, err := client.AddOnsParentProducts().Replace(context.Background(), 410, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AddOnsParentProducts.ReplaceAsync(
    "410",
    new AddOnsParentProductsReplaceOptions
    {
        Resources = JsonConvert.DeserializeObject<List<long>>("[121,120]")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.addOnsParentProducts.replace(addon = "410", resources = listOf(121L, 120L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.add_ons_parent_products.replace(
  addon: 410,
  resources: [121, 120]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::add_ons_parent_products::ReplaceParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceParams::new(serde_json::from_str("{\"resources\":[121,120]}")?);
    let result = client.add_ons_parent_products().replace("410", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AddOnsParentProducts.replace(client, 410, %{"resources" => [121, 120]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp add-ons parent-products replace 410 --body '{"resources":[121,120]}' --yes

```

- Method: `PUT`

- Path: `/v2/addons/{addon}/parent-products`

- Full URL: `https://sell.app/api/v2/addons/{addon}/parent-products`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_ADDON_ID='410'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/addons/${SELLAPP_ADDON_ID}/parent-products" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    121,
    120
  ]
}'
```

## Path Parameters
- `addon` (`integer`, required): The addon path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "uniqueItems": true,
      "items": {
        "type": "integer"
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    121,
    120
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
      "properties": {
        "id": {
          "type": "integer",
          "example": 410
        },
        "store_id": {
          "type": "integer",
          "example": 12
        },
        "title": {
          "type": "string",
          "example": "Customer support"
        },
        "slug": {
          "type": "string",
          "example": "customer-support"
        },
        "description": {
          "type": "string",
          "example": "Priority support for launches scheduled suspiciously close to Friday."
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ],
          "example": "PUBLIC"
        },
        "type": {
          "type": "string",
          "enum": [
            "addon"
          ],
          "example": "addon"
        },
        "is_draft": {
          "type": "boolean",
          "example": true
        },
        "is_discoverable": {
          "type": "boolean",
          "example": false
        },
        "parent_product_ids": {
          "type": "array",
          "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
          "items": {
            "type": "integer"
          },
          "example": [
            120,
            121
          ]
        },
        "variants": {
          "type": "array",
          "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
          "items": {
            "type": "object",
            "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
            "properties": {
              "id": {
                "type": "integer",
                "example": 8801
              },
              "title": {
                "type": "string",
                "example": "Default"
              },
              "is_draft": {
                "type": "boolean",
                "example": false
              }
            },
            "required": [
              "id",
              "title",
              "is_draft"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "store_id",
        "title",
        "slug",
        "description",
        "visibility",
        "type",
        "is_draft",
        "is_discoverable",
        "parent_product_ids",
        "variants",
        "created_at",
        "updated_at",
        "deleted_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 410,
    "store_id": 12,
    "title": "Customer support",
    "slug": "customer-support",
    "description": "Priority support for launches scheduled suspiciously close to Friday.",
    "visibility": "PUBLIC",
    "type": "addon",
    "is_draft": true,
    "is_discoverable": false,
    "parent_product_ids": [
      121,
      120
    ],
    "variants": [],
    "created_at": "2026-07-11T12:00:00.000000Z",
    "updated_at": "2026-07-11T12:00:00.000000Z",
    "deleted_at": null,
    "delivery_text": ""
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Replace product add-ons (/docs/api/add-ons/replace-product-add-ons)

## PUT /v2/products/{product}/addons

Replace a product's add-ons

Replace the complete ordered add-on assignment for a non-subscription product, course, or booking. Newly assigned add-ons must be published, public, and owned by the same store; already assigned non-public add-ons may be retained for safe editing. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.productsAddons.replace({
  "product": 120,
  "resources": [411, 410]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.products_addons.replace(
    product=120,
    resources=[411, 410]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->productsAddons()->replace(
    product: 120,
    resources: [411, 410],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.ProductsAddonsReplaceParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[411,410]}"), params); err != nil { panic(err) }
    result, err := client.ProductsAddons().Replace(context.Background(), 120, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.ProductsAddons.ReplaceAsync(
    "120",
    new ProductsAddonsReplaceOptions
    {
        Resources = JsonConvert.DeserializeObject<List<long>>("[411,410]")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.productsAddons.replace(product = "120", resources = listOf(411L, 410L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.products_addons.replace(
  product: 120,
  resources: [411, 410]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::products_addons::ReplaceParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceParams::new(serde_json::from_str("{\"resources\":[411,410]}")?);
    let result = client.products_addons().replace("120", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.ProductsAddons.replace(client, 120, %{"resources" => [411, 410]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp products addons replace 120 --body '{"resources":[411,410]}' --yes

```

- Method: `PUT`

- Path: `/v2/products/{product}/addons`

- Full URL: `https://sell.app/api/v2/products/{product}/addons`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_ID='120'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/products/${SELLAPP_PRODUCT_ID}/addons" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    411,
    410
  ]
}'
```

## Path Parameters
- `product` (`integer`, required): The product path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "uniqueItems": true,
      "items": {
        "type": "integer"
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    411,
    410
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
        "properties": {
          "id": {
            "type": "integer",
            "example": 410
          },
          "store_id": {
            "type": "integer",
            "example": 12
          },
          "title": {
            "type": "string",
            "example": "Customer support"
          },
          "slug": {
            "type": "string",
            "example": "customer-support"
          },
          "description": {
            "type": "string",
            "example": "Priority support for launches scheduled suspiciously close to Friday."
          },
          "visibility": {
            "type": "string",
            "enum": [
              "PUBLIC",
              "ON_HOLD",
              "HIDDEN",
              "PRIVATE"
            ],
            "example": "PUBLIC"
          },
          "type": {
            "type": "string",
            "enum": [
              "addon"
            ],
            "example": "addon"
          },
          "is_draft": {
            "type": "boolean",
            "example": true
          },
          "is_discoverable": {
            "type": "boolean",
            "example": false
          },
          "parent_product_ids": {
            "type": "array",
            "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
            "items": {
              "type": "integer"
            },
            "example": [
              120,
              121
            ]
          },
          "variants": {
            "type": "array",
            "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
            "items": {
              "type": "object",
              "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
              "properties": {
                "id": {
                  "type": "integer",
                  "example": 8801
                },
                "title": {
                  "type": "string",
                  "example": "Default"
                },
                "is_draft": {
                  "type": "boolean",
                  "example": false
                }
              },
              "required": [
                "id",
                "title",
                "is_draft"
              ]
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "store_id",
          "title",
          "slug",
          "description",
          "visibility",
          "type",
          "is_draft",
          "is_discoverable",
          "parent_product_ids",
          "variants",
          "created_at",
          "updated_at",
          "deleted_at"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 411,
      "store_id": 12,
      "title": "Customer support",
      "slug": "customer-support",
      "description": "Priority support for launches scheduled suspiciously close to Friday.",
      "visibility": "PUBLIC",
      "type": "addon",
      "is_draft": true,
      "is_discoverable": false,
      "parent_product_ids": [
        120
      ],
      "variants": [],
      "created_at": "2026-07-11T12:00:00.000000Z",
      "updated_at": "2026-07-11T12:00:00.000000Z",
      "deleted_at": null,
      "delivery_text": ""
    },
    {
      "id": 410,
      "store_id": 12,
      "title": "Customer support",
      "slug": "customer-support",
      "description": "Priority support for launches scheduled suspiciously close to Friday.",
      "visibility": "PUBLIC",
      "type": "addon",
      "is_draft": true,
      "is_discoverable": false,
      "parent_product_ids": [
        120
      ],
      "variants": [],
      "created_at": "2026-07-11T12:00:00.000000Z",
      "updated_at": "2026-07-11T12:00:00.000000Z",
      "deleted_at": null,
      "delivery_text": ""
    }
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve an add-on (/docs/api/add-ons/retrieve-an-add-on)

## GET /v2/addons/{addon}

Retrieve an add-on

Retrieve one add-on owned by the authenticated store. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.addOns.get({
  "addon": 410
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.add_ons.get(addon=410)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->addOns()->get(addon: 410);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AddOnsGetParams{}
    result, err := client.AddOns().Get(context.Background(), 410, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AddOns.GetAsync(
    "410",
    new AddOnsGetOptions
    {
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.addOns.get(addon = "410")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.add_ons.get(addon: 410)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::add_ons::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.add_ons().get("410", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AddOns.get(client, 410, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp add-ons get 410

```

- Method: `GET`

- Path: `/v2/addons/{addon}`

- Full URL: `https://sell.app/api/v2/addons/{addon}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_ADDON_ID='410'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/addons/${SELLAPP_ADDON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `addon` (`integer`, required): The addon path parameter.

## Query Parameters
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching items in one data array without pagination links or metadata.
- `with_drafts` (`boolean`, optional): Include draft add-ons alongside published add-ons.
- `only_drafts` (`boolean`, optional): Return only draft add-ons.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
      "properties": {
        "id": {
          "type": "integer",
          "example": 410
        },
        "store_id": {
          "type": "integer",
          "example": 12
        },
        "title": {
          "type": "string",
          "example": "Customer support"
        },
        "slug": {
          "type": "string",
          "example": "customer-support"
        },
        "description": {
          "type": "string",
          "example": "Priority support for launches scheduled suspiciously close to Friday."
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ],
          "example": "PUBLIC"
        },
        "type": {
          "type": "string",
          "enum": [
            "addon"
          ],
          "example": "addon"
        },
        "is_draft": {
          "type": "boolean",
          "example": true
        },
        "is_discoverable": {
          "type": "boolean",
          "example": false
        },
        "parent_product_ids": {
          "type": "array",
          "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
          "items": {
            "type": "integer"
          },
          "example": [
            120,
            121
          ]
        },
        "variants": {
          "type": "array",
          "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
          "items": {
            "type": "object",
            "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
            "properties": {
              "id": {
                "type": "integer",
                "example": 8801
              },
              "title": {
                "type": "string",
                "example": "Default"
              },
              "is_draft": {
                "type": "boolean",
                "example": false
              }
            },
            "required": [
              "id",
              "title",
              "is_draft"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "store_id",
        "title",
        "slug",
        "description",
        "visibility",
        "type",
        "is_draft",
        "is_discoverable",
        "parent_product_ids",
        "variants",
        "created_at",
        "updated_at",
        "deleted_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 410,
    "store_id": 12,
    "title": "Customer support",
    "slug": "customer-support",
    "description": "Priority support for launches scheduled suspiciously close to Friday.",
    "visibility": "PUBLIC",
    "type": "addon",
    "is_draft": true,
    "is_discoverable": false,
    "parent_product_ids": [
      120,
      121
    ],
    "variants": [],
    "created_at": "2026-07-11T12:00:00.000000Z",
    "updated_at": "2026-07-11T12:00:00.000000Z",
    "deleted_at": null,
    "delivery_text": ""
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Search add-ons (/docs/api/add-ons/search-add-ons)

## POST /v2/addons/search

Search add-ons

Search add-ons by title, slug, or description and optionally filter or sort the result set. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.addOns.search({
  "filters": [{"field": "id", "operator": "=", "value": 410}],
  "sort": [{"field": "created_at", "direction": "desc"}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.add_ons.search(
    filters=[{"field": "id", "operator": "=", "value": 410}],
    sort=[{"field": "created_at", "direction": "desc"}]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->addOns()->search(
    filters: [['field' => 'id', 'operator' => '=', 'value' => 410]],
    sort: [['field' => 'created_at', 'direction' => 'desc']],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AddOnsSearchParams{}
    if err := json.Unmarshal([]byte("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":410}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}"), params); err != nil { panic(err) }
    page := client.AddOns().Search(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AddOns.SearchAsync(new AddOnsSearchOptions
    {
        Filters = JsonConvert.DeserializeObject<List<SearchAddOnsRequestApplicationJsonPropertyFiltersItem>>("[{\"field\":\"id\",\"operator\":\"=\",\"value\":410}]")!,
        Sort = JsonConvert.DeserializeObject<List<SearchAddOnsRequestApplicationJsonPropertySortItem>>("[{\"field\":\"created_at\",\"direction\":\"desc\"}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.addOns.search(filters = listOf(ObjectMapperFactory.read("{\"field\":\"id\",\"operator\":\"=\",\"value\":410}", app.sell.sellapp.models.SearchAddOnsRequestApplicationJsonPropertyFiltersItem::class.java)), sort = listOf(ObjectMapperFactory.read("{\"field\":\"created_at\",\"direction\":\"desc\"}", app.sell.sellapp.models.SearchAddOnsRequestApplicationJsonPropertySortItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.add_ons.search(
  filters: [{ field: "id", operator: "=", value: 410 }],
  sort: [{ field: "created_at", direction: "desc" }]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::add_ons::SearchParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = SearchParams::new(serde_json::from_str("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":410}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}")?);
    let result = client.add_ons().search(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AddOns.search(client, %{"filters" => [%{"field" => "id", "operator" => "=", "value" => 410}], "sort" => [%{"field" => "created_at", "direction" => "desc"}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp add-ons search --body '{"filters":[{"field":"id","operator":"=","value":410}],"sort":[{"field":"created_at","direction":"desc"}]}'

```

- Method: `POST`

- Path: `/v2/addons/search`

- Full URL: `https://sell.app/api/v2/addons/search`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/addons/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 410
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching items in one data array without pagination links or metadata.
- `with_drafts` (`boolean`, optional): Include draft add-ons alongside published add-ons.
- `only_drafts` (`boolean`, optional): Return only draft add-ons.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "operator": {
            "type": "string",
            "default": "="
          },
          "value": {},
          "type": {
            "type": "string",
            "enum": [
              "and",
              "or"
            ],
            "default": "and"
          },
          "nested": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "anyOf": [
          {
            "required": [
              "field"
            ]
          },
          {
            "required": [
              "nested"
            ]
          }
        ]
      }
    },
    "sort": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "default": "asc"
          }
        },
        "required": [
          "field"
        ]
      }
    },
    "search": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "null"
          ]
        },
        "case_sensitive": {
          "type": "boolean"
        }
      }
    },
    "includes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "relation": {
            "type": "string"
          }
        },
        "required": [
          "relation"
        ]
      }
    }
  }
}
```

Example:

```json
{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 410
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
            "properties": {
              "id": {
                "type": "integer",
                "example": 410
              },
              "store_id": {
                "type": "integer",
                "example": 12
              },
              "title": {
                "type": "string",
                "example": "Customer support"
              },
              "slug": {
                "type": "string",
                "example": "customer-support"
              },
              "description": {
                "type": "string",
                "example": "Priority support for launches scheduled suspiciously close to Friday."
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ],
                "example": "PUBLIC"
              },
              "type": {
                "type": "string",
                "enum": [
                  "addon"
                ],
                "example": "addon"
              },
              "is_draft": {
                "type": "boolean",
                "example": true
              },
              "is_discoverable": {
                "type": "boolean",
                "example": false
              },
              "parent_product_ids": {
                "type": "array",
                "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
                "items": {
                  "type": "integer"
                },
                "example": [
                  120,
                  121
                ]
              },
              "variants": {
                "type": "array",
                "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
                "items": {
                  "type": "object",
                  "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
                  "properties": {
                    "id": {
                      "type": "integer",
                      "example": 8801
                    },
                    "title": {
                      "type": "string",
                      "example": "Default"
                    },
                    "is_draft": {
                      "type": "boolean",
                      "example": false
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "is_draft"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "store_id",
              "title",
              "slug",
              "description",
              "visibility",
              "type",
              "is_draft",
              "is_discoverable",
              "parent_product_ids",
              "variants",
              "created_at",
              "updated_at",
              "deleted_at"
            ]
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
            "properties": {
              "id": {
                "type": "integer",
                "example": 410
              },
              "store_id": {
                "type": "integer",
                "example": 12
              },
              "title": {
                "type": "string",
                "example": "Customer support"
              },
              "slug": {
                "type": "string",
                "example": "customer-support"
              },
              "description": {
                "type": "string",
                "example": "Priority support for launches scheduled suspiciously close to Friday."
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ],
                "example": "PUBLIC"
              },
              "type": {
                "type": "string",
                "enum": [
                  "addon"
                ],
                "example": "addon"
              },
              "is_draft": {
                "type": "boolean",
                "example": true
              },
              "is_discoverable": {
                "type": "boolean",
                "example": false
              },
              "parent_product_ids": {
                "type": "array",
                "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
                "items": {
                  "type": "integer"
                },
                "example": [
                  120,
                  121
                ]
              },
              "variants": {
                "type": "array",
                "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
                "items": {
                  "type": "object",
                  "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
                  "properties": {
                    "id": {
                      "type": "integer",
                      "example": 8801
                    },
                    "title": {
                      "type": "string",
                      "example": "Default"
                    },
                    "is_draft": {
                      "type": "boolean",
                      "example": false
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "is_draft"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "store_id",
              "title",
              "slug",
              "description",
              "visibility",
              "type",
              "is_draft",
              "is_discoverable",
              "parent_product_ids",
              "variants",
              "created_at",
              "updated_at",
              "deleted_at"
            ]
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 410,
      "store_id": 12,
      "title": "Customer support",
      "slug": "customer-support",
      "description": "Priority support for launches scheduled suspiciously close to Friday.",
      "visibility": "PUBLIC",
      "type": "addon",
      "is_draft": true,
      "is_discoverable": false,
      "parent_product_ids": [
        120,
        121
      ],
      "variants": [],
      "created_at": "2026-07-11T12:00:00.000000Z",
      "updated_at": "2026-07-11T12:00:00.000000Z",
      "deleted_at": null,
      "delivery_text": ""
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/addons/search?page=1",
    "last": "https://sell.app/api/v2/addons/search?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/addons/search",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/addons/search?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Update an add-on (/docs/api/add-ons/update-an-add-on)

## PATCH /v2/addons/{addon}

Update an add-on

Update an add-on and optionally replace its ordered parent-product assignments. Publication is rejected unless the add-on has exactly one published, fixed-price, single-payment variant. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.addOns.update({
  "addon": 410,
  "description": "Priority email, chat, and launch-day reassurance.",
  "isDraft": false
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.add_ons.update(
    addon=410,
    description="Priority email, chat, and launch-day reassurance.",
    is_draft=False
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->addOns()->update(
    addon: 410,
    description: 'Priority email, chat, and launch-day reassurance.',
    isDraft: false,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AddOnsUpdateParams{}
    if err := json.Unmarshal([]byte("{\"description\":\"Priority email, chat, and launch-day reassurance.\",\"is_draft\":false}"), params); err != nil { panic(err) }
    result, err := client.AddOns().Update(context.Background(), 410, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AddOns.UpdateAsync(
    "410",
    new AddOnsUpdateOptions
    {
        Description = "Priority email, chat, and launch-day reassurance.",
        IsDraft = false,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.addOns.update(addon = "410", description = app.sell.sellapp.common.http.PatchField.Present("Priority email, chat, and launch-day reassurance."), isDraft = app.sell.sellapp.common.http.PatchField.Present(false))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.add_ons.update(
  addon: 410,
  description: "Priority email, chat, and launch-day reassurance.",
  is_draft: false
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::add_ons::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{\"description\":\"Priority email, chat, and launch-day reassurance.\",\"is_draft\":false}")?);
    let result = client.add_ons().update("410", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AddOns.update(client, 410, %{"description" => "Priority email, chat, and launch-day reassurance.", "is_draft" => false})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp add-ons update 410 --description 'Priority email, chat, and launch-day reassurance.' --is-draft false --yes

```

- Method: `PATCH`

- Path: `/v2/addons/{addon}`

- Full URL: `https://sell.app/api/v2/addons/{addon}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_ADDON_ID='410'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/addons/${SELLAPP_ADDON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "description": "Priority email, chat, and launch-day reassurance.",
  "is_draft": false
}'
```

## Path Parameters
- `addon` (`integer`, required): The addon path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255,
      "description": "Seller-facing title for the add-on."
    },
    "slug": {
      "type": "string",
      "maxLength": 255,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "description": "Optional store-unique slug. When omitted during creation, SellApp generates one from the title."
    },
    "description": {
      "type": "string",
      "minLength": 5,
      "maxLength": 5000,
      "description": "Description shown when the add-on is offered."
    },
    "visibility": {
      "type": "string",
      "enum": [
        "PUBLIC",
        "ON_HOLD",
        "HIDDEN",
        "PRIVATE"
      ]
    },
    "is_draft": {
      "type": "boolean",
      "description": "New add-ons are always drafts. Set this to false only after creating exactly one published, fixed-price, single-payment variant through `/v2/products/{addon}/variants`."
    },
    "parent_product_ids": {
      "type": "array",
      "uniqueItems": true,
      "description": "Ordered IDs of same-store, non-subscription products, courses, or bookings to assign. Supplying the field replaces the complete assignment set.",
      "items": {
        "type": "integer"
      }
    }
  }
}
```

Example:

```json
{
  "description": "Priority email, chat, and launch-day reassurance.",
  "is_draft": false
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "description": "A checkout add-on that can be assigned to eligible products, courses, and bookings in the same store.",
      "properties": {
        "id": {
          "type": "integer",
          "example": 410
        },
        "store_id": {
          "type": "integer",
          "example": 12
        },
        "title": {
          "type": "string",
          "example": "Customer support"
        },
        "slug": {
          "type": "string",
          "example": "customer-support"
        },
        "description": {
          "type": "string",
          "example": "Priority support for launches scheduled suspiciously close to Friday."
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ],
          "example": "PUBLIC"
        },
        "type": {
          "type": "string",
          "enum": [
            "addon"
          ],
          "example": "addon"
        },
        "is_draft": {
          "type": "boolean",
          "example": true
        },
        "is_discoverable": {
          "type": "boolean",
          "example": false
        },
        "parent_product_ids": {
          "type": "array",
          "description": "Ordered IDs of products, courses, and bookings that offer this add-on.",
          "items": {
            "type": "integer"
          },
          "example": [
            120,
            121
          ]
        },
        "variants": {
          "type": "array",
          "description": "Add-ons support exactly one fixed-price, single-payment variant when published.",
          "items": {
            "type": "object",
            "description": "A compact variant reference. Use the product variant endpoints with this add-on ID as the product path parameter to manage pricing and fulfillment.",
            "properties": {
              "id": {
                "type": "integer",
                "example": 8801
              },
              "title": {
                "type": "string",
                "example": "Default"
              },
              "is_draft": {
                "type": "boolean",
                "example": false
              }
            },
            "required": [
              "id",
              "title",
              "is_draft"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "store_id",
        "title",
        "slug",
        "description",
        "visibility",
        "type",
        "is_draft",
        "is_discoverable",
        "parent_product_ids",
        "variants",
        "created_at",
        "updated_at",
        "deleted_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 410,
    "store_id": 12,
    "title": "Customer support",
    "slug": "customer-support",
    "description": "Priority email, chat, and launch-day reassurance.",
    "visibility": "PUBLIC",
    "type": "addon",
    "is_draft": false,
    "is_discoverable": true,
    "parent_product_ids": [
      120,
      121
    ],
    "variants": [],
    "created_at": "2026-07-11T12:00:00.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "deleted_at": null,
    "delivery_text": ""
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Create an affiliate payout (/docs/api/affiliates/create-payout)

Create a record for the affiliate's eligible commissions. This does not send money; your store arranges the payment separately.

Send a unique `Idempotency-Key` header. Replaying the same key for the same affiliate returns the original payout. Reusing it for another affiliate is rejected.

## POST /v2/affiliates/{affiliate}/payouts

Create an affiliate payout

Create a payout record for all eligible accepted referrals of one active affiliate. The merchant arranges payment separately. Replaying the same Idempotency-Key returns the same record. Requires `affiliate`, `affiliate:payout`, and enough eligible commissions to meet the store's minimum payout amount. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliatePayouts.create({
  "affiliate": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_payouts.create(affiliate=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliatePayouts()->create(affiliate: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.AffiliatePayouts().Create(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliatePayouts.CreateAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliatePayouts.create(affiliate = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_payouts.create(affiliate: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_payouts::CreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateParams::default();
    let result = client.affiliate_payouts().create("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliatePayouts.create(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-payouts create 1 --yes

```

- Method: `POST`

- Path: `/v2/affiliates/{affiliate}/payouts`

- Full URL: `https://sell.app/api/v2/affiliates/{affiliate}/payouts`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_AFFILIATE_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliates/${SELLAPP_AFFILIATE_ID}/payouts" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Idempotency-Key: replace-me'
```

## Path Parameters
- `affiliate` (`integer`, required): The affiliate path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, required): A caller-generated key, unique per store and affiliate payout operation.

## Request Body
No request body.

## Responses

### 200

Previously created payout returned for an idempotent replay.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "affiliate_id": {
          "type": "integer"
        },
        "affiliate_email": {
          "type": "string",
          "format": "email"
        },
        "amount_usd_cents": {
          "type": "integer",
          "minimum": 0
        },
        "status": {
          "type": "string",
          "enum": [
            "due",
            "paid",
            "cancelled"
          ]
        },
        "payout_method": {
          "type": [
            "string",
            "null"
          ]
        },
        "payout_account": {
          "type": "string",
          "readOnly": true,
          "description": "A masked payout destination. Full payout credentials are never returned."
        },
        "referrals_count": {
          "type": "integer",
          "minimum": 0
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "affiliate_id",
        "amount_usd_cents",
        "status",
        "payout_account",
        "referrals_count"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 91,
    "affiliate_id": 88,
    "affiliate_email": "alex@example.com",
    "amount_usd_cents": 2000,
    "status": "due",
    "payout_method": "PAYPAL",
    "payout_account": "a***@example.com",
    "referrals_count": 10,
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 201

Affiliate payout created and eligible referrals reserved.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "affiliate_id": {
          "type": "integer"
        },
        "affiliate_email": {
          "type": "string",
          "format": "email"
        },
        "amount_usd_cents": {
          "type": "integer",
          "minimum": 0
        },
        "status": {
          "type": "string",
          "enum": [
            "due",
            "paid",
            "cancelled"
          ]
        },
        "payout_method": {
          "type": [
            "string",
            "null"
          ]
        },
        "payout_account": {
          "type": "string",
          "readOnly": true,
          "description": "A masked payout destination. Full payout credentials are never returned."
        },
        "referrals_count": {
          "type": "integer",
          "minimum": 0
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "affiliate_id",
        "amount_usd_cents",
        "status",
        "payout_account",
        "referrals_count"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 91,
    "affiliate_id": 88,
    "affiliate_email": "alex@example.com",
    "amount_usd_cents": 2000,
    "status": "due",
    "payout_method": "PAYPAL",
    "payout_account": "a***@example.com",
    "referrals_count": 10,
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Overview (/docs/api/affiliates)



See who refers customers to your store, review the commissions they earn, and manage their payouts. Responses include store memberships, approved profile details, referral sessions, linked orders, and balances.

Affiliate payouts are merchant-managed records of referral commissions. SellApp identifies eligible commissions and records payout state; it does not transfer or hold funds for these payouts. Arrange payment yourself, then record it as paid. Amounts and balances use integer USD cents: `1999` means $19.99. Each referral links to a purchase and its line item.

Use these token abilities:

* `affiliate` for reads.
* `affiliate:write` in addition to `affiliate` for affiliate approval/rejection and referral review decisions.
* `affiliate:payout` in addition to `affiliate` for payout creation and recording payment.
* `affiliate:sensitive` in addition to `affiliate` for full referral session identifiers.

Payout creation requires an `Idempotency-Key`. The first request atomically reserves every eligible accepted referral for that affiliate. Replaying the same key returns the same payout instead of creating a duplicate. Payout status changes update the payout and every linked referral in one transaction; identical retries are no-ops.

Payout destinations are masked in API responses. Referral session identifiers are sensitive and should not be logged or exposed to buyers.

OAuth integrations use the operation's `payments:read` or `payments:write` scope
with `X-STORE`. The user's current store permissions must also permit the action.

To change program rules or invite affiliates, use [Affiliate program](/api/affiliate-program).

## Endpoints [#endpoints]

* [List affiliates](/api/affiliates/list-affiliates)
* [Retrieve an affiliate](/api/affiliates/retrieve-affiliate)
* [Update affiliate status](/api/affiliates/update-affiliate-status)
* [List affiliate referrals](/api/affiliates/list-referrals)
* [Retrieve or review a referral](/api/affiliates/manage-referral)
* [List referral sessions](/api/affiliates/list-referral-sessions)
* [List affiliate payouts](/api/affiliates/list-payouts)
* [Create an affiliate payout](/api/affiliates/create-payout)
* [Update affiliate payout status](/api/affiliates/update-payout-status)


# List affiliates (/docs/api/affiliates/list-affiliates)

## GET /v2/affiliates

List affiliates

List store affiliate memberships, approved profile details, referral counts, and integer USD-cent balances. Requires the `affiliate` ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliates.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliates.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliates()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AffiliatesListParams{}
    page := client.Affiliates().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Affiliates.ListAsync(new AffiliatesListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliates.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliates.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliates::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.affiliates().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Affiliates.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliates list

```

- Method: `GET`

- Path: `/v2/affiliates`

- Full URL: `https://sell.app/api/v2/affiliates`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliates" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `status` (`string`, optional): Filter by affiliate program status.
- `search` (`string`, optional): Search affiliate email addresses and profile identifiers.
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "disabled",
              "rejected",
              "blocked"
            ]
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "payout_method": {
            "type": [
              "string",
              "null"
            ]
          },
          "profile": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "integer"
                  },
                  "identifier": {
                    "type": "string"
                  },
                  "bio": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "sites": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "socials": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "status": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "pending",
                      "approved",
                      "rejected",
                      null
                    ]
                  },
                  "email_subscribers": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "web_visitors": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "balances": {
            "type": "object",
            "properties": {
              "available_usd_cents": {
                "type": "integer",
                "minimum": 0
              },
              "pending_usd_cents": {
                "type": "integer",
                "minimum": 0
              },
              "paid_usd_cents": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "available_usd_cents",
              "pending_usd_cents",
              "paid_usd_cents"
            ]
          },
          "referrals_count": {
            "type": "integer",
            "minimum": 0
          },
          "payouts_count": {
            "type": "integer",
            "minimum": 0
          },
          "invited_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "application_submitted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "email",
          "status",
          "profile",
          "balances",
          "referrals_count",
          "payouts_count"
        ]
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example (minimal):

```json
{
  "data": [
    {
      "id": 88,
      "email": "alex@example.com",
      "status": "pending",
      "reason": null,
      "payout_method": null,
      "profile": null,
      "balances": {
        "available_usd_cents": 0,
        "pending_usd_cents": 0,
        "paid_usd_cents": 0
      },
      "referrals_count": 0,
      "payouts_count": 0,
      "invited_at": "2026-09-01T12:00:00Z",
      "application_submitted_at": null,
      "created_at": "2026-09-01T12:00:00Z",
      "updated_at": "2026-09-01T12:00:00Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/affiliates?page=1",
    "last": "https://sell.app/api/v2/affiliates?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/affiliates?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ],
    "path": "https://sell.app/api/v2/affiliates",
    "per_page": 15,
    "to": 1,
    "total": 1
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# List affiliate payouts (/docs/api/affiliates/list-payouts)

These records track referral commissions and payments arranged by your store.
SellApp does not transfer money through these endpoints.

Responses can include cancelled historical payouts. The payout status update
endpoint supports marking a due payout paid or reopening a paid payout as due.

## GET /v2/affiliate-payouts

List affiliate payouts

List merchant-managed affiliate payout records. These record commission payments arranged by the merchant; SellApp does not transfer or hold the funds. Requires the `affiliate` credential ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliatePayouts.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_payouts.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliatePayouts()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AffiliatePayoutsListParams{}
    page := client.AffiliatePayouts().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliatePayouts.ListAsync(new AffiliatePayoutsListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliatePayouts.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_payouts.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_payouts::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.affiliate_payouts().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliatePayouts.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-payouts list

```

- Method: `GET`

- Path: `/v2/affiliate-payouts`

- Full URL: `https://sell.app/api/v2/affiliate-payouts`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliate-payouts" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `affiliate_id` (`integer`, optional): Filter by affiliate ID.
- `status` (`string`, optional): Filter by payout status.
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "affiliate_id": {
            "type": "integer"
          },
          "affiliate_email": {
            "type": "string",
            "format": "email"
          },
          "amount_usd_cents": {
            "type": "integer",
            "minimum": 0
          },
          "status": {
            "type": "string",
            "enum": [
              "due",
              "paid",
              "cancelled"
            ]
          },
          "payout_method": {
            "type": [
              "string",
              "null"
            ]
          },
          "payout_account": {
            "type": "string",
            "readOnly": true,
            "description": "A masked payout destination. Full payout credentials are never returned."
          },
          "referrals_count": {
            "type": "integer",
            "minimum": 0
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "affiliate_id",
          "amount_usd_cents",
          "status",
          "payout_account",
          "referrals_count"
        ]
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example (minimal):

```json
{
  "data": [
    {
      "id": 91,
      "affiliate_id": 88,
      "affiliate_email": "alex@example.com",
      "amount_usd_cents": 2000,
      "status": "due",
      "payout_method": "PAYPAL",
      "payout_account": "a***@example.com",
      "referrals_count": 10,
      "created_at": "2026-09-01T12:00:00Z",
      "updated_at": "2026-09-01T12:00:00Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/affiliate-payouts?page=1",
    "last": "https://sell.app/api/v2/affiliate-payouts?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/affiliate-payouts?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ],
    "path": "https://sell.app/api/v2/affiliate-payouts",
    "per_page": 15,
    "to": 1,
    "total": 1
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/affiliate-payouts/{payout}

Retrieve an affiliate payout

Retrieve one merchant-managed affiliate payout record with a masked destination and referral count. Requires the `affiliate` credential ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliatePayouts.get({
  "payout": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_payouts.get(payout=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliatePayouts()->get(payout: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.AffiliatePayouts().Get(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliatePayouts.GetAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliatePayouts.get(payout = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_payouts.get(payout: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_payouts::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.affiliate_payouts().get("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliatePayouts.get(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-payouts get 1

```

- Method: `GET`

- Path: `/v2/affiliate-payouts/{payout}`

- Full URL: `https://sell.app/api/v2/affiliate-payouts/{payout}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PAYOUT_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliate-payouts/${SELLAPP_PAYOUT_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `payout` (`integer`, required): The payout path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "affiliate_id": {
          "type": "integer"
        },
        "affiliate_email": {
          "type": "string",
          "format": "email"
        },
        "amount_usd_cents": {
          "type": "integer",
          "minimum": 0
        },
        "status": {
          "type": "string",
          "enum": [
            "due",
            "paid",
            "cancelled"
          ]
        },
        "payout_method": {
          "type": [
            "string",
            "null"
          ]
        },
        "payout_account": {
          "type": "string",
          "readOnly": true,
          "description": "A masked payout destination. Full payout credentials are never returned."
        },
        "referrals_count": {
          "type": "integer",
          "minimum": 0
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "affiliate_id",
        "amount_usd_cents",
        "status",
        "payout_account",
        "referrals_count"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 91,
    "affiliate_id": 88,
    "affiliate_email": "alex@example.com",
    "amount_usd_cents": 2000,
    "status": "due",
    "payout_method": "PAYPAL",
    "payout_account": "a***@example.com",
    "referrals_count": 10,
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# List referral sessions (/docs/api/affiliates/list-referral-sessions)

Session identifiers are sensitive attribution tokens. Avoid including them in application logs, reports, or buyer-facing responses.

These endpoints require both `affiliate` and `affiliate:sensitive`.

## GET /v2/affiliate-referral-sessions

List affiliate referral sessions

List store-scoped referral attribution sessions. Session identifiers are sensitive. Requires `affiliate` and `affiliate:sensitive`. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliateReferralSessions.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_referral_sessions.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliateReferralSessions()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AffiliateReferralSessionsListParams{}
    page := client.AffiliateReferralSessions().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliateReferralSessions.ListAsync(new AffiliateReferralSessionsListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliateReferralSessions.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_referral_sessions.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_referral_sessions::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.affiliate_referral_sessions().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliateReferralSessions.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-referral-sessions list

```

- Method: `GET`

- Path: `/v2/affiliate-referral-sessions`

- Full URL: `https://sell.app/api/v2/affiliate-referral-sessions`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliate-referral-sessions" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `affiliate_id` (`integer`, optional): Filter by affiliate ID.
- `active` (`boolean`, optional): Return active or expired sessions.
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "session_id": {
            "type": "string",
            "description": "The tracked referral session identifier. Treat this value as sensitive."
          },
          "affiliate_id": {
            "type": "integer"
          },
          "affiliate_email": {
            "type": "string",
            "format": "email"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "session_id",
          "affiliate_id"
        ]
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example (minimal):

```json
{
  "data": [
    {
      "id": 90,
      "session_id": "launch-lab-referral-session",
      "affiliate_id": 88,
      "affiliate_email": "alex@example.com",
      "expires_at": "2026-10-01T12:00:00Z",
      "created_at": "2026-09-01T12:00:00Z",
      "updated_at": "2026-09-01T12:00:00Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/affiliate-referral-sessions?page=1",
    "last": "https://sell.app/api/v2/affiliate-referral-sessions?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/affiliate-referral-sessions?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ],
    "path": "https://sell.app/api/v2/affiliate-referral-sessions",
    "per_page": 15,
    "to": 1,
    "total": 1
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/affiliate-referral-sessions/{referralSession}

Retrieve an affiliate referral session

Retrieve one store-scoped referral attribution session. Requires `affiliate` and `affiliate:sensitive`. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliateReferralSessions.get({
  "referralSession": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_referral_sessions.get(referral_session=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliateReferralSessions()->get(referralSession: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.AffiliateReferralSessions().Get(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliateReferralSessions.GetAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliateReferralSessions.get(referralSession = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_referral_sessions.get(referral_session: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_referral_sessions::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.affiliate_referral_sessions().get("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliateReferralSessions.get(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-referral-sessions get 1

```

- Method: `GET`

- Path: `/v2/affiliate-referral-sessions/{referralSession}`

- Full URL: `https://sell.app/api/v2/affiliate-referral-sessions/{referralSession}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_REFERRAL_SESSION_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliate-referral-sessions/${SELLAPP_REFERRAL_SESSION_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `referralSession` (`integer`, required): The referralSession path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "session_id": {
          "type": "string",
          "description": "The tracked referral session identifier. Treat this value as sensitive."
        },
        "affiliate_id": {
          "type": "integer"
        },
        "affiliate_email": {
          "type": "string",
          "format": "email"
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "session_id",
        "affiliate_id"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 90,
    "session_id": "launch-lab-referral-session",
    "affiliate_id": 88,
    "affiliate_email": "alex@example.com",
    "expires_at": "2026-10-01T12:00:00Z",
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# List affiliate referrals (/docs/api/affiliates/list-referrals)

Percentage commissions expose `commission.percentage` as a decimal string. Fixed commissions expose `commission.amount_usd_cents` as integer USD cents; the unused value is `null`.

## GET /v2/affiliate-referrals

List affiliate referrals

List store referrals with their attributed order and purchase line item. Requires the `affiliate` credential ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliateReferrals.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_referrals.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliateReferrals()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AffiliateReferralsListParams{}
    page := client.AffiliateReferrals().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliateReferrals.ListAsync(new AffiliateReferralsListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliateReferrals.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_referrals.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_referrals::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.affiliate_referrals().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliateReferrals.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-referrals list

```

- Method: `GET`

- Path: `/v2/affiliate-referrals`

- Full URL: `https://sell.app/api/v2/affiliate-referrals`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliate-referrals" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `affiliate_id` (`integer`, optional): Filter by store affiliate ID.
- `order_id` (`integer`, optional): Filter by attributed Order ID.
- `status` (`string`, optional): Filter by referral status.
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "affiliate_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "affiliate_email": {
            "type": "string",
            "format": "email"
          },
          "order_id": {
            "type": "integer",
            "description": "The attributed Order ID."
          },
          "invoice_v2_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The attributed purchase line-item ID."
          },
          "product_variant_id": {
            "type": "integer"
          },
          "product_title": {
            "type": [
              "string",
              "null"
            ]
          },
          "variant_title": {
            "type": [
              "string",
              "null"
            ]
          },
          "customer_id": {
            "type": "integer"
          },
          "amount_usd_cents": {
            "type": "integer",
            "minimum": 0
          },
          "commission": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "percentage",
                  "fixed"
                ]
              },
              "percentage": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The percentage commission as a decimal string when type is percentage."
              },
              "amount_usd_cents": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0,
                "description": "The fixed commission in integer USD cents when type is fixed."
              }
            },
            "required": [
              "type",
              "percentage",
              "amount_usd_cents"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "created",
              "accepted",
              "in_review",
              "pending",
              "paid",
              "rejected",
              "void",
              "expired"
            ]
          },
          "eligible_for_payout_at": {
            "type": "string",
            "format": "date-time"
          },
          "payout_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "affiliate_id",
          "order_id",
          "invoice_v2_id",
          "product_variant_id",
          "amount_usd_cents",
          "commission",
          "status"
        ]
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example (minimal):

```json
{
  "data": [
    {
      "id": 89,
      "affiliate_id": 88,
      "affiliate_email": "alex@example.com",
      "order_id": 9001,
      "invoice_v2_id": 9002,
      "product_variant_id": 4321,
      "product_title": "Design kit",
      "variant_title": "Standard",
      "customer_id": 77,
      "amount_usd_cents": 200,
      "commission": {
        "type": "percentage",
        "percentage": "10",
        "amount_usd_cents": null
      },
      "status": "created",
      "eligible_for_payout_at": "2026-10-01T12:00:00Z",
      "payout_id": null,
      "created_at": "2026-09-01T12:00:00Z",
      "updated_at": "2026-09-01T12:00:00Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/affiliate-referrals?page=1",
    "last": "https://sell.app/api/v2/affiliate-referrals?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/affiliate-referrals?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ],
    "path": "https://sell.app/api/v2/affiliate-referrals",
    "per_page": 15,
    "to": 1,
    "total": 1
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve or review a referral (/docs/api/affiliates/manage-referral)

Once a referral is assigned to a payout, change it through the payout status endpoint so the payout and referral ledger remain consistent.

## GET /v2/affiliate-referrals/{referral}

Retrieve an affiliate referral

Retrieve a referral and its attributed order and purchase line item. Requires the `affiliate` credential ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliateReferrals.get({
  "referral": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_referrals.get(referral=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliateReferrals()->get(referral: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.AffiliateReferrals().Get(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliateReferrals.GetAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliateReferrals.get(referral = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_referrals.get(referral: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_referrals::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.affiliate_referrals().get("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliateReferrals.get(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-referrals get 1

```

- Method: `GET`

- Path: `/v2/affiliate-referrals/{referral}`

- Full URL: `https://sell.app/api/v2/affiliate-referrals/{referral}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_REFERRAL_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliate-referrals/${SELLAPP_REFERRAL_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `referral` (`integer`, required): The referral path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "affiliate_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "affiliate_email": {
          "type": "string",
          "format": "email"
        },
        "order_id": {
          "type": "integer",
          "description": "The attributed Order ID."
        },
        "invoice_v2_id": {
          "type": [
            "integer",
            "null"
          ],
          "description": "The attributed purchase line-item ID."
        },
        "product_variant_id": {
          "type": "integer"
        },
        "product_title": {
          "type": [
            "string",
            "null"
          ]
        },
        "variant_title": {
          "type": [
            "string",
            "null"
          ]
        },
        "customer_id": {
          "type": "integer"
        },
        "amount_usd_cents": {
          "type": "integer",
          "minimum": 0
        },
        "commission": {
          "type": "object",
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "percentage",
                "fixed"
              ]
            },
            "percentage": {
              "type": [
                "string",
                "null"
              ],
              "description": "The percentage commission as a decimal string when type is percentage."
            },
            "amount_usd_cents": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "description": "The fixed commission in integer USD cents when type is fixed."
            }
          },
          "required": [
            "type",
            "percentage",
            "amount_usd_cents"
          ]
        },
        "status": {
          "type": "string",
          "enum": [
            "created",
            "accepted",
            "in_review",
            "pending",
            "paid",
            "rejected",
            "void",
            "expired"
          ]
        },
        "eligible_for_payout_at": {
          "type": "string",
          "format": "date-time"
        },
        "payout_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "affiliate_id",
        "order_id",
        "invoice_v2_id",
        "product_variant_id",
        "amount_usd_cents",
        "commission",
        "status"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 89,
    "affiliate_id": 88,
    "affiliate_email": "alex@example.com",
    "order_id": 9001,
    "invoice_v2_id": 9002,
    "product_variant_id": 4321,
    "product_title": "Design kit",
    "variant_title": "Standard",
    "customer_id": 77,
    "amount_usd_cents": 200,
    "commission": {
      "type": "percentage",
      "percentage": "10",
      "amount_usd_cents": null
    },
    "status": "created",
    "eligible_for_payout_at": "2026-10-01T12:00:00Z",
    "payout_id": null,
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v2/affiliate-referrals/{referral}/status

Update referral status

Move an unassigned referral through a valid review, acceptance, or rejection transition. Referrals already assigned to a payout cannot be changed independently. Requires `affiliate` and `affiliate:write`. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliateReferrals.update({
  "referral": 71,
  "status": "accepted"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_referrals.update(
    referral=71,
    status="accepted"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliateReferrals()->update(
    referral: 71,
    status: 'accepted',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AffiliateReferralsUpdateParams{}
    if err := json.Unmarshal([]byte("{\"status\":\"accepted\"}"), params); err != nil { panic(err) }
    result, err := client.AffiliateReferrals().Update(context.Background(), 71, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliateReferrals.UpdateAsync(
    "71",
    new AffiliateReferralsUpdateOptions
    {
        Status = JsonConvert.DeserializeObject<SdkUpdateReferralStatusRequestApplicationJsonStatus>("\"accepted\"")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliateReferrals.update(referral = "71", status = app.sell.sellapp.types.SdkUpdateReferralStatusRequestApplicationJsonStatus("accepted"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_referrals.update(
  referral: 71,
  status: "accepted"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_referrals::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{\"status\":\"accepted\"}")?);
    let result = client.affiliate_referrals().update("71", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliateReferrals.update(client, 71, %{"status" => "accepted"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-referrals update 71 --status accepted --yes

```

- Method: `PATCH`

- Path: `/v2/affiliate-referrals/{referral}/status`

- Full URL: `https://sell.app/api/v2/affiliate-referrals/{referral}/status`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_REFERRAL_ID='71'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliate-referrals/${SELLAPP_REFERRAL_ID}/status" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "status": "accepted"
}'
```

## Path Parameters
- `referral` (`integer`, required): The referral path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "accepted",
        "in_review",
        "rejected"
      ]
    }
  },
  "required": [
    "status"
  ]
}
```

Example:

```json
{
  "status": "accepted"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "affiliate_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "affiliate_email": {
          "type": "string",
          "format": "email"
        },
        "order_id": {
          "type": "integer",
          "description": "The attributed Order ID."
        },
        "invoice_v2_id": {
          "type": [
            "integer",
            "null"
          ],
          "description": "The attributed purchase line-item ID."
        },
        "product_variant_id": {
          "type": "integer"
        },
        "product_title": {
          "type": [
            "string",
            "null"
          ]
        },
        "variant_title": {
          "type": [
            "string",
            "null"
          ]
        },
        "customer_id": {
          "type": "integer"
        },
        "amount_usd_cents": {
          "type": "integer",
          "minimum": 0
        },
        "commission": {
          "type": "object",
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "percentage",
                "fixed"
              ]
            },
            "percentage": {
              "type": [
                "string",
                "null"
              ],
              "description": "The percentage commission as a decimal string when type is percentage."
            },
            "amount_usd_cents": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "description": "The fixed commission in integer USD cents when type is fixed."
            }
          },
          "required": [
            "type",
            "percentage",
            "amount_usd_cents"
          ]
        },
        "status": {
          "type": "string",
          "enum": [
            "created",
            "accepted",
            "in_review",
            "pending",
            "paid",
            "rejected",
            "void",
            "expired"
          ]
        },
        "eligible_for_payout_at": {
          "type": "string",
          "format": "date-time"
        },
        "payout_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "affiliate_id",
        "order_id",
        "invoice_v2_id",
        "product_variant_id",
        "amount_usd_cents",
        "commission",
        "status"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 71,
    "affiliate_id": 42,
    "affiliate_email": "alex.morgan@example.com",
    "order_id": 9001,
    "invoice_v2_id": 9002,
    "product_variant_id": 4321,
    "customer_id": 125,
    "product_title": "Founder memo circle",
    "variant_title": "Monthly membership",
    "amount_usd_cents": 200,
    "commission": {
      "type": "percentage",
      "percentage": "10",
      "amount_usd_cents": null
    },
    "status": "accepted",
    "payout_id": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve an affiliate (/docs/api/affiliates/retrieve-affiliate)

## GET /v2/affiliates/{affiliate}

Retrieve an affiliate

Retrieve one store-scoped affiliate, profile, balances, and counts. Requires the `affiliate` ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliates.get({
  "affiliate": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliates.get(affiliate=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliates()->get(affiliate: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Affiliates().Get(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Affiliates.GetAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliates.get(affiliate = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliates.get(affiliate: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliates::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.affiliates().get("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Affiliates.get(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliates get 1

```

- Method: `GET`

- Path: `/v2/affiliates/{affiliate}`

- Full URL: `https://sell.app/api/v2/affiliates/{affiliate}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_AFFILIATE_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliates/${SELLAPP_AFFILIATE_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `affiliate` (`integer`, required): The affiliate path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "status": {
          "type": "string",
          "enum": [
            "pending",
            "active",
            "disabled",
            "rejected",
            "blocked"
          ]
        },
        "reason": {
          "type": [
            "string",
            "null"
          ]
        },
        "payout_method": {
          "type": [
            "string",
            "null"
          ]
        },
        "profile": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "identifier": {
                  "type": "string"
                },
                "bio": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "sites": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "format": "uri"
                  }
                },
                "socials": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "format": "uri"
                  }
                },
                "status": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "enum": [
                    "pending",
                    "approved",
                    "rejected",
                    null
                  ]
                },
                "email_subscribers": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "web_visitors": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "balances": {
          "type": "object",
          "properties": {
            "available_usd_cents": {
              "type": "integer",
              "minimum": 0
            },
            "pending_usd_cents": {
              "type": "integer",
              "minimum": 0
            },
            "paid_usd_cents": {
              "type": "integer",
              "minimum": 0
            }
          },
          "required": [
            "available_usd_cents",
            "pending_usd_cents",
            "paid_usd_cents"
          ]
        },
        "referrals_count": {
          "type": "integer",
          "minimum": 0
        },
        "payouts_count": {
          "type": "integer",
          "minimum": 0
        },
        "invited_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "application_submitted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "email",
        "status",
        "profile",
        "balances",
        "referrals_count",
        "payouts_count"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 88,
    "email": "alex@example.com",
    "status": "pending",
    "reason": null,
    "payout_method": null,
    "profile": null,
    "balances": {
      "available_usd_cents": 0,
      "pending_usd_cents": 0,
      "paid_usd_cents": 0
    },
    "referrals_count": 0,
    "payouts_count": 0,
    "invited_at": "2026-09-01T12:00:00Z",
    "application_submitted_at": null,
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Update affiliate status (/docs/api/affiliates/update-affiliate-status)

The transition must be valid for the current state. A pending invitation cannot become active until the invitee submits an application.

## PATCH /v2/affiliates/{affiliate}/status

Update affiliate status

Approve, disable, re-enable, or reject an affiliate through its valid state transition. Requires `affiliate` and `affiliate:write`; pending invitations cannot be approved until an application is submitted. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliates.update({
  "affiliate": 42,
  "status": "active"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliates.update(
    affiliate=42,
    status="active"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliates()->update(
    affiliate: 42,
    status: 'active',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AffiliatesUpdateParams{}
    if err := json.Unmarshal([]byte("{\"status\":\"active\"}"), params); err != nil { panic(err) }
    result, err := client.Affiliates().Update(context.Background(), 42, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Affiliates.UpdateAsync(
    "42",
    new AffiliatesUpdateOptions
    {
        Status = JsonConvert.DeserializeObject<SdkUpdateAffiliateStatusRequestApplicationJsonStatus>("\"active\"")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliates.update(affiliate = "42", status = app.sell.sellapp.types.SdkUpdateAffiliateStatusRequestApplicationJsonStatus("active"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliates.update(
  affiliate: 42,
  status: "active"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliates::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{\"status\":\"active\"}")?);
    let result = client.affiliates().update("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Affiliates.update(client, 42, %{"status" => "active"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliates update 42 --status active --yes

```

- Method: `PATCH`

- Path: `/v2/affiliates/{affiliate}/status`

- Full URL: `https://sell.app/api/v2/affiliates/{affiliate}/status`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_AFFILIATE_ID='42'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliates/${SELLAPP_AFFILIATE_ID}/status" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "status": "active"
}'
```

## Path Parameters
- `affiliate` (`integer`, required): The affiliate path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "active",
        "disabled",
        "rejected"
      ]
    }
  },
  "required": [
    "status"
  ]
}
```

Example:

```json
{
  "status": "active"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "status": {
          "type": "string",
          "enum": [
            "pending",
            "active",
            "disabled",
            "rejected",
            "blocked"
          ]
        },
        "reason": {
          "type": [
            "string",
            "null"
          ]
        },
        "payout_method": {
          "type": [
            "string",
            "null"
          ]
        },
        "profile": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "identifier": {
                  "type": "string"
                },
                "bio": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "sites": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "format": "uri"
                  }
                },
                "socials": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "format": "uri"
                  }
                },
                "status": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "enum": [
                    "pending",
                    "approved",
                    "rejected",
                    null
                  ]
                },
                "email_subscribers": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "web_visitors": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "balances": {
          "type": "object",
          "properties": {
            "available_usd_cents": {
              "type": "integer",
              "minimum": 0
            },
            "pending_usd_cents": {
              "type": "integer",
              "minimum": 0
            },
            "paid_usd_cents": {
              "type": "integer",
              "minimum": 0
            }
          },
          "required": [
            "available_usd_cents",
            "pending_usd_cents",
            "paid_usd_cents"
          ]
        },
        "referrals_count": {
          "type": "integer",
          "minimum": 0
        },
        "payouts_count": {
          "type": "integer",
          "minimum": 0
        },
        "invited_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "application_submitted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "email",
        "status",
        "profile",
        "balances",
        "referrals_count",
        "payouts_count"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 42,
    "email": "alex.morgan@example.com",
    "status": "active",
    "profile": null,
    "balances": {
      "available_usd_cents": 0,
      "pending_usd_cents": 0,
      "paid_usd_cents": 0
    },
    "referrals_count": 0,
    "payouts_count": 0
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Update affiliate payout status (/docs/api/affiliates/update-payout-status)

Mark a payout paid only after your store has arranged payment. This operation
records payment status; it does not transfer money. The payout amount must
match its linked commission total. Identical retries do not add duplicate history.

## PATCH /v2/affiliate-payouts/{payout}/status

Update affiliate payout status

Mark an affiliate payout record due or paid and update its assigned referrals. Marking paid records a payment arranged by the merchant; it does not transfer money. Identical retries make no further change. Requires `affiliate` and `affiliate:payout`. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliatePayouts.update({
  "payout": 1,
  "status": "paid"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_payouts.update(
    payout=1,
    status="paid"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliatePayouts()->update(
    payout: 1,
    status: 'paid',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AffiliatePayoutsUpdateParams{}
    if err := json.Unmarshal([]byte("{\"status\":\"paid\"}"), params); err != nil { panic(err) }
    result, err := client.AffiliatePayouts().Update(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliatePayouts.UpdateAsync(
    "1",
    new AffiliatePayoutsUpdateOptions
    {
        Status = JsonConvert.DeserializeObject<SdkUpdateAffiliatePayoutStatusRequestApplicationJsonStatus>("\"paid\"")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliatePayouts.update(payout = "1", status = app.sell.sellapp.types.AffiliatePayoutsStatus("paid"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_payouts.update(
  payout: 1,
  status: "paid"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_payouts::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{\"status\":\"paid\"}")?);
    let result = client.affiliate_payouts().update("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliatePayouts.update(client, 1, %{"status" => "paid"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-payouts update 1 --status paid --yes

```

- Method: `PATCH`

- Path: `/v2/affiliate-payouts/{payout}/status`

- Full URL: `https://sell.app/api/v2/affiliate-payouts/{payout}/status`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PAYOUT_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliate-payouts/${SELLAPP_PAYOUT_ID}/status" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "status": "paid"
}'
```

## Path Parameters
- `payout` (`integer`, required): The payout path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "due",
        "paid"
      ]
    }
  },
  "required": [
    "status"
  ]
}
```

Example (minimal):

```json
{
  "status": "paid"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "affiliate_id": {
          "type": "integer"
        },
        "affiliate_email": {
          "type": "string",
          "format": "email"
        },
        "amount_usd_cents": {
          "type": "integer",
          "minimum": 0
        },
        "status": {
          "type": "string",
          "enum": [
            "due",
            "paid",
            "cancelled"
          ]
        },
        "payout_method": {
          "type": [
            "string",
            "null"
          ]
        },
        "payout_account": {
          "type": "string",
          "readOnly": true,
          "description": "A masked payout destination. Full payout credentials are never returned."
        },
        "referrals_count": {
          "type": "integer",
          "minimum": 0
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "affiliate_id",
        "amount_usd_cents",
        "status",
        "payout_account",
        "referrals_count"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 0,
    "affiliate_id": 0,
    "affiliate_email": "maya@example.com",
    "amount_usd_cents": 0,
    "status": "paid",
    "payout_method": "string",
    "payout_account": "string",
    "referrals_count": 0,
    "created_at": "2019-08-24T14:15:22Z",
    "updated_at": "2019-08-24T14:15:22Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Overview (/docs/api/affiliate-program)



Set commission rules for your affiliate program, choose eligible products, and invite people to join. Use an API key with the `affiliate` ability or OAuth with the operation's `payments:read` or `payments:write` scope. Current store permissions also apply.

## Endpoints [#endpoints]

* [Retrieve affiliate program configuration](/api/affiliate-program/retrieve-affiliate-program)
* [Replace affiliate program configuration](/api/affiliate-program/replace-affiliate-program)
* [List pending invitations](/api/affiliate-program/list-affiliate-invitations)
* [Invite an affiliate](/api/affiliate-program/invite-an-affiliate)

Configuration is replaced as one change: either the whole update succeeds or none of it does. When `enabled_specific_products` is `true`, send the complete `products` array. Despite the field name, each ID must identify a **product variant** in the selected store. An empty array disables every existing store-level product restriction.

Invitation creation emails a single-use onboarding link. The secret link is never returned in API responses. Duplicate invitations and invitations while the program is disabled return a validation error.


# Invite an affiliate (/docs/api/affiliate-program/invite-an-affiliate)

## POST /v2/affiliate-invitations

Invite an affiliate

Create a pending affiliate invitation and email a single-use onboarding link. Duplicate invitations are rejected and invites are rate limited per store. The affiliate program must be enabled. Requires the `affiliate` token ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliateProgram.invite({
  "email": "alex.morgan@example.com"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_program.invite(email="alex.morgan@example.com")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliateProgram()->invite(email: 'alex.morgan@example.com');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AffiliateProgramInviteParams{}
    if err := json.Unmarshal([]byte("{\"email\":\"alex.morgan@example.com\"}"), params); err != nil { panic(err) }
    result, err := client.AffiliateProgram().Invite(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliateProgram.InviteAsync(new AffiliateProgramInviteOptions
    {
        Email = "alex.morgan@example.com",
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliateProgram.invite(email = "alex.morgan@example.com")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_program.invite(email: "alex.morgan@example.com")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_program::InviteParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = InviteParams::new(serde_json::from_str("{\"email\":\"alex.morgan@example.com\"}")?);
    let result = client.affiliate_program().invite(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliateProgram.invite(client, %{"email" => "alex.morgan@example.com"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-program invite --email 'alex.morgan@example.com' --yes

```

- Method: `POST`

- Path: `/v2/affiliate-invitations`

- Full URL: `https://sell.app/api/v2/affiliate-invitations`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliate-invitations" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "email": "alex.morgan@example.com"
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "format": "email",
      "maxLength": 255
    }
  },
  "required": [
    "email"
  ]
}
```

Example:

```json
{
  "email": "alex.morgan@example.com"
}
```

## Responses

### 201

Invitation created and delivered.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "status": {
          "type": "string",
          "enum": [
            "pending"
          ]
        },
        "invited_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "application_submitted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "email",
        "status",
        "invited_at",
        "application_submitted_at",
        "created_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 77,
    "email": "alex.morgan@example.com",
    "status": "pending",
    "invited_at": "2026-07-12T12:00:00Z",
    "application_submitted_at": null,
    "created_at": "2026-07-12T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# List pending affiliate invitations (/docs/api/affiliate-program/list-affiliate-invitations)

## GET /v2/affiliate-invitations

List pending affiliate invitations

List pending invitations that have not completed affiliate onboarding. The one-time onboarding link is delivered by email and is never returned by the API. Requires the `affiliate` token ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliateProgram.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_program.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliateProgram()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AffiliateProgramListParams{}
    page := client.AffiliateProgram().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliateProgram.ListAsync(new AffiliateProgramListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliateProgram.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_program.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_program::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.affiliate_program().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliateProgram.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-program list

```

- Method: `GET`

- Path: `/v2/affiliate-invitations`

- Full URL: `https://sell.app/api/v2/affiliate-invitations`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliate-invitations" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending"
            ]
          },
          "invited_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "application_submitted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "email",
          "status",
          "invited_at",
          "application_submitted_at",
          "created_at"
        ]
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example (minimal):

```json
{
  "data": [
    {
      "id": 88,
      "email": "alex@example.com",
      "status": "pending",
      "invited_at": "2026-09-01T12:00:00Z",
      "application_submitted_at": null,
      "created_at": "2026-09-01T12:00:00Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/affiliate-invitations?page=1",
    "last": "https://sell.app/api/v2/affiliate-invitations?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/affiliate-invitations?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ],
    "path": "https://sell.app/api/v2/affiliate-invitations",
    "per_page": 15,
    "to": 1,
    "total": 1
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Replace affiliate program configuration (/docs/api/affiliate-program/replace-affiliate-program)

Product-specific percentage commissions use `commission.percentage`. Fixed commissions use integer USD cents in `commission.amount_usd_cents`.

## PUT /v2/affiliate-program

Replace affiliate program configuration

Replace the complete affiliate-program configuration. The products array is authoritative: enabled entries replace existing store-level product restrictions, and every variant ID must belong to the authenticated store. Requires the `affiliate` token ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliateProgram.replace({
  "enabled": true,
  "settings": {"autoApproveAffiliates": false, "minimumPayout": "25", "commission": {"type": "percentage", "amount": "20"}, "referrerType": "first_referrer", "trackingLength": 30, "subscriptionCommission": true, "enabledSpecificProducts": true, "payoutMethods": ["PAYPAL"], "enableHub": false},
  "products": [{"id": 42, "enabled": true, "commission": {"type": "percentage", "percentage": "25"}}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_program.replace(
    enabled=True,
    settings={
        "auto_approve_affiliates": False,
        "minimum_payout": "25",
        "commission": {"type": "percentage", "amount": "20"},
        "referrer_type": "first_referrer",
        "tracking_length": 30,
        "subscription_commission": True,
        "enabled_specific_products": True,
        "payout_methods": ["PAYPAL"],
        "enable_hub": False
    },
    products=[
        {
            "id": 42,
            "enabled": True,
            "commission": {"type": "percentage", "percentage": "25"}
        }
    ]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliateProgram()->replace(
    enabled: true,
    settings: [
        'auto_approve_affiliates' => false,
        'minimum_payout' => '25',
        'commission' => ['type' => 'percentage', 'amount' => '20'],
        'referrer_type' => 'first_referrer',
        'tracking_length' => 30,
        'subscription_commission' => true,
        'enabled_specific_products' => true,
        'payout_methods' => ['PAYPAL'],
        'enable_hub' => false,
    ],
    products: [
        [
            'id' => 42,
            'enabled' => true,
            'commission' => ['type' => 'percentage', 'percentage' => '25'],
        ],
    ],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.AffiliateProgramReplaceParams{}
    if err := json.Unmarshal([]byte("{\"enabled\":true,\"settings\":{\"auto_approve_affiliates\":false,\"minimum_payout\":\"25\",\"commission\":{\"type\":\"percentage\",\"amount\":\"20\"},\"referrer_type\":\"first_referrer\",\"tracking_length\":30,\"subscription_commission\":true,\"enabled_specific_products\":true,\"payout_methods\":[\"PAYPAL\"],\"enable_hub\":false},\"products\":[{\"id\":42,\"enabled\":true,\"commission\":{\"type\":\"percentage\",\"percentage\":\"25\"}}]}"), params); err != nil { panic(err) }
    result, err := client.AffiliateProgram().Replace(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliateProgram.ReplaceAsync(new AffiliateProgramReplaceOptions
    {
        Enabled = true,
        Settings = JsonConvert.DeserializeObject<ReplaceAffiliateProgramConfigurationRequestApplicationJsonPropertySettings>("{\"auto_approve_affiliates\":false,\"minimum_payout\":\"25\",\"commission\":{\"type\":\"percentage\",\"amount\":\"20\"},\"referrer_type\":\"first_referrer\",\"tracking_length\":30,\"subscription_commission\":true,\"enabled_specific_products\":true,\"payout_methods\":[\"PAYPAL\"],\"enable_hub\":false}")!,
        Products = JsonConvert.DeserializeObject<List<ReplaceAffiliateProgramConfigurationRequestApplicationJsonPropertyProductsItem>>("[{\"id\":42,\"enabled\":true,\"commission\":{\"type\":\"percentage\",\"percentage\":\"25\"}}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliateProgram.replace(enabled = true, settings = ObjectMapperFactory.read("{\"auto_approve_affiliates\":false,\"minimum_payout\":\"25\",\"commission\":{\"type\":\"percentage\",\"amount\":\"20\"},\"referrer_type\":\"first_referrer\",\"tracking_length\":30,\"subscription_commission\":true,\"enabled_specific_products\":true,\"payout_methods\":[\"PAYPAL\"],\"enable_hub\":false}", app.sell.sellapp.models.ReplaceAffiliateProgramConfigurationRequestApplicationJsonPropertySettings::class.java), products = listOf(ObjectMapperFactory.read("{\"id\":42,\"enabled\":true,\"commission\":{\"type\":\"percentage\",\"percentage\":\"25\"}}", app.sell.sellapp.models.ReplaceAffiliateProgramConfigurationRequestApplicationJsonPropertyProductsItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_program.replace(
  enabled: true,
  settings: {
    auto_approve_affiliates: false,
    minimum_payout: "25",
    commission: { type: "percentage", amount: "20" },
    referrer_type: "first_referrer",
    tracking_length: 30,
    subscription_commission: true,
    enabled_specific_products: true,
    payout_methods: ["PAYPAL"],
    enable_hub: false
  },
  products: [
    { id: 42, enabled: true, commission: { type: "percentage", percentage: "25" } }
  ]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_program::ReplaceParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceParams::new(serde_json::from_str("{\"enabled\":true,\"settings\":{\"auto_approve_affiliates\":false,\"minimum_payout\":\"25\",\"commission\":{\"type\":\"percentage\",\"amount\":\"20\"},\"referrer_type\":\"first_referrer\",\"tracking_length\":30,\"subscription_commission\":true,\"enabled_specific_products\":true,\"payout_methods\":[\"PAYPAL\"],\"enable_hub\":false},\"products\":[{\"id\":42,\"enabled\":true,\"commission\":{\"type\":\"percentage\",\"percentage\":\"25\"}}]}")?);
    let result = client.affiliate_program().replace(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliateProgram.replace(client, %{"enabled" => true, "settings" => %{"auto_approve_affiliates" => false, "minimum_payout" => "25", "commission" => %{"type" => "percentage", "amount" => "20"}, "referrer_type" => "first_referrer", "tracking_length" => 30, "subscription_commission" => true, "enabled_specific_products" => true, "payout_methods" => ["PAYPAL"], "enable_hub" => false}, "products" => [%{"id" => 42, "enabled" => true, "commission" => %{"type" => "percentage", "percentage" => "25"}}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-program replace --body '{"enabled":true,"settings":{"auto_approve_affiliates":false,"minimum_payout":"25","commission":{"type":"percentage","amount":"20"},"referrer_type":"first_referrer","tracking_length":30,"subscription_commission":true,"enabled_specific_products":true,"payout_methods":["PAYPAL"],"enable_hub":false},"products":[{"id":42,"enabled":true,"commission":{"type":"percentage","percentage":"25"}}]}' --yes

```

- Method: `PUT`

- Path: `/v2/affiliate-program`

- Full URL: `https://sell.app/api/v2/affiliate-program`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliate-program" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "enabled": true,
  "settings": {
    "auto_approve_affiliates": false,
    "minimum_payout": "25",
    "commission": {
      "type": "percentage",
      "amount": "20"
    },
    "referrer_type": "first_referrer",
    "tracking_length": 30,
    "subscription_commission": true,
    "enabled_specific_products": true,
    "payout_methods": [
      "PAYPAL"
    ],
    "enable_hub": false
  },
  "products": [
    {
      "id": 42,
      "enabled": true,
      "commission": {
        "type": "percentage",
        "percentage": "25"
      }
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "enabled": {
      "type": "boolean"
    },
    "settings": {
      "type": "object",
      "properties": {
        "auto_approve_affiliates": {
          "type": "boolean"
        },
        "minimum_payout": {
          "type": "string",
          "description": "Minimum payout balance in USD major units.",
          "example": "25"
        },
        "commission": {
          "type": "object",
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "percentage",
                "fixed"
              ]
            },
            "amount": {
              "type": "string",
              "description": "Decimal commission value. Percentage commissions must be from 0.01 through 100; fixed commissions are USD major units.",
              "example": "20"
            }
          },
          "required": [
            "type",
            "amount"
          ]
        },
        "referrer_type": {
          "type": "string",
          "enum": [
            "first_referrer",
            "last_referrer"
          ]
        },
        "tracking_length": {
          "type": "integer",
          "minimum": 1,
          "maximum": 90
        },
        "subscription_commission": {
          "type": "boolean"
        },
        "enabled_specific_products": {
          "type": "boolean"
        },
        "payout_methods": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string",
            "enum": [
              "PAYPAL",
              "CASHAPP",
              "VENMO",
              "WISE",
              "BTC",
              "LTC",
              "ETH",
              "XMR",
              "SOL",
              "ADA",
              "BNB",
              "TRX",
              "MATIC",
              "ETH_USDT",
              "ETH_USDC",
              "ETH_UNI",
              "ETH_SHIB",
              "ETH_DAI"
            ]
          }
        },
        "enable_hub": {
          "type": "boolean"
        }
      },
      "required": [
        "auto_approve_affiliates",
        "minimum_payout",
        "commission",
        "referrer_type",
        "tracking_length",
        "subscription_commission",
        "enabled_specific_products",
        "payout_methods",
        "enable_hub"
      ]
    },
    "products": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "A product variant ID owned by the authenticated store."
          },
          "enabled": {
            "type": "boolean"
          },
          "commission": {
            "anyOf": [
              {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "percentage"
                      },
                      "percentage": {
                        "type": "string"
                      },
                      "amount_usd_cents": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      }
                    },
                    "required": [
                      "type",
                      "percentage"
                    ],
                    "additionalProperties": false
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "fixed"
                      },
                      "percentage": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "amount_usd_cents": {
                        "type": "integer",
                        "minimum": 1
                      }
                    },
                    "required": [
                      "type",
                      "amount_usd_cents"
                    ],
                    "additionalProperties": false
                  }
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Required when enabled is true; ignored when enabled is false."
          }
        },
        "required": [
          "id",
          "enabled"
        ]
      }
    }
  },
  "required": [
    "enabled",
    "settings",
    "products"
  ]
}
```

Example:

```json
{
  "enabled": true,
  "settings": {
    "auto_approve_affiliates": false,
    "minimum_payout": "25",
    "commission": {
      "type": "percentage",
      "amount": "20"
    },
    "referrer_type": "first_referrer",
    "tracking_length": 30,
    "subscription_commission": true,
    "enabled_specific_products": true,
    "payout_methods": [
      "PAYPAL"
    ],
    "enable_hub": false
  },
  "products": [
    {
      "id": 42,
      "enabled": true,
      "commission": {
        "type": "percentage",
        "percentage": "25"
      }
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "enabled": {
          "type": "boolean"
        },
        "settings": {
          "type": "object",
          "properties": {
            "auto_approve_affiliates": {
              "type": "boolean"
            },
            "minimum_payout": {
              "type": [
                "string",
                "null"
              ],
              "description": "Minimum payout balance in USD major units, or null before initial configuration.",
              "example": "25"
            },
            "commission": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "enum": [
                    "percentage",
                    "fixed"
                  ]
                },
                "amount": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Decimal commission value, or null before the store has configured its affiliate program.",
                  "example": "20"
                }
              },
              "required": [
                "type",
                "amount"
              ]
            },
            "referrer_type": {
              "type": "string",
              "enum": [
                "first_referrer",
                "last_referrer"
              ]
            },
            "tracking_length": {
              "type": "integer",
              "minimum": 1,
              "maximum": 90
            },
            "subscription_commission": {
              "type": "boolean"
            },
            "enabled_specific_products": {
              "type": "boolean"
            },
            "payout_methods": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "PAYPAL",
                  "CASHAPP",
                  "VENMO",
                  "WISE",
                  "BTC",
                  "LTC",
                  "ETH",
                  "XMR",
                  "SOL",
                  "ADA",
                  "BNB",
                  "TRX",
                  "MATIC",
                  "ETH_USDT",
                  "ETH_USDC",
                  "ETH_UNI",
                  "ETH_SHIB",
                  "ETH_DAI"
                ]
              },
              "description": "The payout methods affiliates may choose from. Empty until the store configures them; configuration writes must include at least one."
            },
            "enable_hub": {
              "type": "boolean"
            }
          },
          "required": [
            "auto_approve_affiliates",
            "minimum_payout",
            "commission",
            "referrer_type",
            "tracking_length",
            "subscription_commission",
            "enabled_specific_products",
            "payout_methods",
            "enable_hub"
          ]
        },
        "products": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "product_id": {
                "type": "integer"
              },
              "product_title": {
                "type": "string"
              },
              "variant_title": {
                "type": "string"
              },
              "enabled": {
                "type": "boolean",
                "const": true
              },
              "commission": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "percentage",
                      "fixed"
                    ]
                  },
                  "percentage": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Decimal percentage from 0.01 through 100."
                  },
                  "amount_usd_cents": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "description": "Fixed commission in integer USD cents."
                  }
                },
                "required": [
                  "type",
                  "percentage",
                  "amount_usd_cents"
                ]
              }
            },
            "required": [
              "id",
              "product_id",
              "product_title",
              "variant_title",
              "enabled",
              "commission"
            ]
          }
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "enabled",
        "settings",
        "products",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 12,
    "enabled": true,
    "settings": {
      "auto_approve_affiliates": false,
      "minimum_payout": "25",
      "commission": {
        "type": "percentage",
        "amount": "20"
      },
      "referrer_type": "first_referrer",
      "tracking_length": 30,
      "subscription_commission": true,
      "enabled_specific_products": true,
      "payout_methods": [
        "PAYPAL"
      ],
      "enable_hub": false
    },
    "products": [
      {
        "id": 42,
        "product_id": 9,
        "product_title": "The Cold-Email Warmup Club",
        "variant_title": "Definitely Personalised",
        "enabled": true,
        "commission": {
          "type": "percentage",
          "percentage": "25",
          "amount_usd_cents": null
        }
      }
    ],
    "created_at": "2026-07-12T12:00:00Z",
    "updated_at": "2026-07-12T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve affiliate program configuration (/docs/api/affiliate-program/retrieve-affiliate-program)

## GET /v2/affiliate-program

Retrieve affiliate program configuration

Retrieve the authenticated store's affiliate-program enablement, commissions, tracking settings, payout preferences, and selected product variants. Requires the `affiliate` token ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.affiliateProgram.get();
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.affiliate_program.get()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->affiliateProgram()->get();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.AffiliateProgram().Get(context.Background())
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.AffiliateProgram.GetAsync();
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.affiliateProgram.get()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.affiliate_program.get
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::affiliate_program::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.affiliate_program().get(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.AffiliateProgram.get(client)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp affiliate-program get

```

- Method: `GET`

- Path: `/v2/affiliate-program`

- Full URL: `https://sell.app/api/v2/affiliate-program`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/affiliate-program" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "enabled": {
          "type": "boolean"
        },
        "settings": {
          "type": "object",
          "properties": {
            "auto_approve_affiliates": {
              "type": "boolean"
            },
            "minimum_payout": {
              "type": [
                "string",
                "null"
              ],
              "description": "Minimum payout balance in USD major units, or null before initial configuration.",
              "example": "25"
            },
            "commission": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "enum": [
                    "percentage",
                    "fixed"
                  ]
                },
                "amount": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Decimal commission value, or null before the store has configured its affiliate program.",
                  "example": "20"
                }
              },
              "required": [
                "type",
                "amount"
              ]
            },
            "referrer_type": {
              "type": "string",
              "enum": [
                "first_referrer",
                "last_referrer"
              ]
            },
            "tracking_length": {
              "type": "integer",
              "minimum": 1,
              "maximum": 90
            },
            "subscription_commission": {
              "type": "boolean"
            },
            "enabled_specific_products": {
              "type": "boolean"
            },
            "payout_methods": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "PAYPAL",
                  "CASHAPP",
                  "VENMO",
                  "WISE",
                  "BTC",
                  "LTC",
                  "ETH",
                  "XMR",
                  "SOL",
                  "ADA",
                  "BNB",
                  "TRX",
                  "MATIC",
                  "ETH_USDT",
                  "ETH_USDC",
                  "ETH_UNI",
                  "ETH_SHIB",
                  "ETH_DAI"
                ]
              },
              "description": "The payout methods affiliates may choose from. Empty until the store configures them; configuration writes must include at least one."
            },
            "enable_hub": {
              "type": "boolean"
            }
          },
          "required": [
            "auto_approve_affiliates",
            "minimum_payout",
            "commission",
            "referrer_type",
            "tracking_length",
            "subscription_commission",
            "enabled_specific_products",
            "payout_methods",
            "enable_hub"
          ]
        },
        "products": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "product_id": {
                "type": "integer"
              },
              "product_title": {
                "type": "string"
              },
              "variant_title": {
                "type": "string"
              },
              "enabled": {
                "type": "boolean",
                "const": true
              },
              "commission": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "percentage",
                      "fixed"
                    ]
                  },
                  "percentage": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Decimal percentage from 0.01 through 100."
                  },
                  "amount_usd_cents": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "description": "Fixed commission in integer USD cents."
                  }
                },
                "required": [
                  "type",
                  "percentage",
                  "amount_usd_cents"
                ]
              }
            },
            "required": [
              "id",
              "product_id",
              "product_title",
              "variant_title",
              "enabled",
              "commission"
            ]
          }
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "enabled",
        "settings",
        "products",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 12,
    "enabled": true,
    "settings": {
      "auto_approve_affiliates": false,
      "minimum_payout": "25",
      "commission": {
        "type": "percentage",
        "amount": "20"
      },
      "referrer_type": "first_referrer",
      "tracking_length": 30,
      "subscription_commission": true,
      "enabled_specific_products": true,
      "payout_methods": [
        "PAYPAL"
      ],
      "enable_hub": false
    },
    "products": [
      {
        "id": 42,
        "product_id": 9,
        "product_title": "The Cold-Email Warmup Club",
        "variant_title": "Definitely Personalised",
        "enabled": true,
        "commission": {
          "type": "percentage",
          "percentage": "25",
          "amount_usd_cents": null
        }
      }
    ],
    "created_at": "2026-07-12T12:00:00Z",
    "updated_at": "2026-07-12T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Create a Blacklist Rule (/docs/api/blacklists/create-blacklist)

## POST /v2/blacklists

Create a blacklist rule

Create a store-scoped blacklist rule. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.blacklists.v2CreateBlacklist({
  "type": "EMAIL",
  "data": "blocked@example.com",
  "description": "Blocked after a verified fraud report."
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.blacklists.v2_create_blacklist(
    type="EMAIL",
    data="blocked@example.com",
    description="Blocked after a verified fraud report."
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->blacklists()->v2CreateBlacklist(
    type: 'EMAIL',
    data: 'blocked@example.com',
    description: 'Blocked after a verified fraud report.',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.BlacklistsV2CreateBlacklistParams{}
    if err := json.Unmarshal([]byte("{\"type\":\"EMAIL\",\"data\":\"blocked@example.com\",\"description\":\"Blocked after a verified fraud report.\"}"), params); err != nil { panic(err) }
    result, err := client.Blacklists().V2CreateBlacklist(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Blacklists.V2CreateBlacklistAsync(new BlacklistsV2CreateBlacklistOptions
    {
        Type = JsonConvert.DeserializeObject<BlacklistType>("\"EMAIL\"")!,
        Data = "blocked@example.com",
        Description = "Blocked after a verified fraud report.",
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.blacklists.v2CreateBlacklist(type = app.sell.sellapp.types.BlacklistType("EMAIL"), data = "blocked@example.com", description = "Blocked after a verified fraud report.")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.blacklists.v2_create_blacklist(
  type: "EMAIL",
  data: "blocked@example.com",
  description: "Blocked after a verified fraud report."
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::blacklists::V2CreateBlacklistParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2CreateBlacklistParams::new(serde_json::from_str("{\"type\":\"EMAIL\",\"data\":\"blocked@example.com\",\"description\":\"Blocked after a verified fraud report.\"}")?);
    let result = client.blacklists().v_2_create_blacklist(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Blacklists.v2_create_blacklist(client, %{"type" => "EMAIL", "data" => "blocked@example.com", "description" => "Blocked after a verified fraud report."})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp blacklists v-2-create-blacklist --type EMAIL --data 'blocked@example.com' --description 'Blocked after a verified fraud report.' --yes

```

- Method: `POST`

- Path: `/v2/blacklists`

- Full URL: `https://sell.app/api/v2/blacklists`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `support:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/blacklists" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "type": "EMAIL",
  "data": "blocked@example.com",
  "description": "Blocked after a verified fraud report."
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, optional): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "data",
    "description"
  ],
  "properties": {
    "type": {
      "type": "string",
      "description": "The type of blacklist rule.",
      "enum": [
        "ASN",
        "COUNTRY",
        "EMAIL",
        "IP",
        "WILDCARD_EMAIL"
      ]
    },
    "data": {
      "type": "string",
      "description": "The value to blacklist.",
      "example": "@blocked.example"
    },
    "description": {
      "type": "string",
      "description": "Why this rule is being created.",
      "example": "Retired after the growth experiment ended."
    }
  },
  "example": {
    "type": "WILDCARD_EMAIL",
    "data": "@blocked.example",
    "description": "Retired after the growth experiment ended."
  }
}
```

Example:

```json
{
  "type": "EMAIL",
  "data": "blocked@example.com",
  "description": "Blocked after a verified fraud report."
}
```

## Responses

### 201

Created.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A blacklist rule that blocks purchases matching the provided details.",
      "required": [
        "id",
        "type",
        "data",
        "description",
        "created_at",
        "updated_at",
        "store_id"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "description": "Unique identifier for the blacklist rule.",
          "example": 1
        },
        "type": {
          "type": "string",
          "description": "The type of blacklist rule.",
          "enum": [
            "ASN",
            "COUNTRY",
            "EMAIL",
            "IP",
            "WILDCARD_EMAIL"
          ]
        },
        "data": {
          "type": "string",
          "description": "The data associated with the rule type, such as an IP address, email, or country code.",
          "example": "leo.martin@example.com"
        },
        "description": {
          "type": "string",
          "description": "Why this blacklist rule exists.",
          "example": "Block the address used by our launch-day load-test bot."
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was created.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was last updated.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "store_id": {
          "type": "integer",
          "description": "The store ID this blacklist rule belongs to.",
          "example": 1
        }
      }
    }
  },
  "example": {
    "data": {
      "id": 1,
      "type": "WILDCARD_EMAIL",
      "data": "@blocked.example",
      "description": "Retired after the growth experiment ended.",
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 42,
    "type": "EMAIL",
    "data": "blocked@example.com",
    "description": "Blocked after a verified fraud report.",
    "created_at": "2026-09-04T09:00:00Z",
    "updated_at": "2026-09-04T09:00:00Z",
    "store_id": 12
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Delete a Blacklist Rule (/docs/api/blacklists/delete-blacklist)

## DELETE /v2/blacklists/{blacklist}

Delete a blacklist rule

Delete a blacklist rule in the selected store. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.blacklists.v2DeleteBlacklist({
  "blacklist": 42
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.blacklists.v2_delete_blacklist(blacklist=42)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->blacklists()->v2DeleteBlacklist(blacklist: 42);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    if err := client.Blacklists().V2DeleteBlacklist(context.Background(), 42); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.Blacklists.V2DeleteBlacklistAsync("42");
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.blacklists.v2DeleteBlacklist(blacklist = "42")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.blacklists.v2_delete_blacklist(blacklist: 42)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::blacklists::V2DeleteBlacklistParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2DeleteBlacklistParams::default();
    let result = client.blacklists().v_2_delete_blacklist("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Blacklists.v2_delete_blacklist(client, 42)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp blacklists v-2-delete-blacklist 42 --yes

```

- Method: `DELETE`

- Path: `/v2/blacklists/{blacklist}`

- Full URL: `https://sell.app/api/v2/blacklists/{blacklist}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `support:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_BLACKLIST_ID='42'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v2/blacklists/${SELLAPP_BLACKLIST_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `blacklist` (`integer`, required): The blacklist identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A blacklist rule that blocks purchases matching the provided details.",
      "required": [
        "id",
        "type",
        "data",
        "description",
        "created_at",
        "updated_at",
        "store_id"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "description": "Unique identifier for the blacklist rule.",
          "example": 1
        },
        "type": {
          "type": "string",
          "description": "The type of blacklist rule.",
          "enum": [
            "ASN",
            "COUNTRY",
            "EMAIL",
            "IP",
            "WILDCARD_EMAIL"
          ]
        },
        "data": {
          "type": "string",
          "description": "The data associated with the rule type, such as an IP address, email, or country code.",
          "example": "leo.martin@example.com"
        },
        "description": {
          "type": "string",
          "description": "Why this blacklist rule exists.",
          "example": "Block the address used by our launch-day load-test bot."
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was created.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was last updated.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "store_id": {
          "type": "integer",
          "description": "The store ID this blacklist rule belongs to.",
          "example": 1
        }
      }
    }
  },
  "example": {
    "data": {
      "id": 1,
      "type": "WILDCARD_EMAIL",
      "data": "@blocked.example",
      "description": "Retired after the growth experiment ended.",
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 42,
    "type": "EMAIL",
    "data": "blocked@example.com",
    "description": "Blocked after a verified fraud report.",
    "created_at": "2026-09-04T09:00:00Z",
    "updated_at": "2026-09-04T09:00:00Z",
    "store_id": 12
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Overview (/docs/api/blacklists)

Blacklist rules block checkout attempts that match an email, IP address,
country, or autonomous system number (ASN, which identifies a network). Use the description to
leave your team a clear reason for the rule.

Rules are store-scoped and affect real purchase attempts as soon as they are
active. Verify the selected `X-STORE` before creating or deleting one. The
operation schemas define the accepted rule types, data format, and timestamps.
Only authorized callers can read sensitive rule data.

## Endpoints [#endpoints]

* [List rules](/api/blacklists/list-blacklists)
* [Create a rule](/api/blacklists/create-blacklist)
* [Retrieve a rule](/api/blacklists/retrieve-blacklist)
* [Update a rule](/api/blacklists/update-blacklist)
* [Delete a rule](/api/blacklists/delete-blacklist)

## Additional endpoint reference [#additional-endpoint-reference]

## PUT /v2/blacklists/{blacklist}

Replace a blacklist rule

Replace a blacklist rule in the selected store. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.blacklists.v2ReplaceBlacklist({
  "blacklist": 42,
  "description": "Blocked after a verified fraud report."
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.blacklists.v2_replace_blacklist(
    blacklist=42,
    description="Blocked after a verified fraud report."
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->blacklists()->v2ReplaceBlacklist(
    blacklist: 42,
    description: 'Blocked after a verified fraud report.',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.BlacklistsV2ReplaceBlacklistParams{}
    if err := json.Unmarshal([]byte("{\"description\":\"Blocked after a verified fraud report.\"}"), params); err != nil { panic(err) }
    result, err := client.Blacklists().V2ReplaceBlacklist(context.Background(), 42, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Blacklists.V2ReplaceBlacklistAsync(
    "42",
    new BlacklistsV2ReplaceBlacklistOptions
    {
        Description = "Blocked after a verified fraud report.",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.blacklists.v2ReplaceBlacklist(blacklist = "42", description = "Blocked after a verified fraud report.")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.blacklists.v2_replace_blacklist(
  blacklist: 42,
  description: "Blocked after a verified fraud report."
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::blacklists::V2ReplaceBlacklistParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2ReplaceBlacklistParams::new(serde_json::from_str("{\"description\":\"Blocked after a verified fraud report.\"}")?);
    let result = client.blacklists().v_2_replace_blacklist("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Blacklists.v2_replace_blacklist(client, 42, %{"description" => "Blocked after a verified fraud report."})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp blacklists v-2-replace-blacklist 42 --description 'Blocked after a verified fraud report.' --yes

```

- Method: `PUT`

- Path: `/v2/blacklists/{blacklist}`

- Full URL: `https://sell.app/api/v2/blacklists/{blacklist}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `support:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_BLACKLIST_ID='42'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/blacklists/${SELLAPP_BLACKLIST_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "description": "Blocked after a verified fraud report."
}'
```

## Path Parameters
- `blacklist` (`integer`, required): The blacklist identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, optional): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "description": "Provide one or more fields to update an existing blacklist rule.",
  "properties": {
    "type": {
      "type": "string",
      "description": "The type of blacklist rule.",
      "enum": [
        "ASN",
        "COUNTRY",
        "EMAIL",
        "IP",
        "WILDCARD_EMAIL"
      ]
    },
    "data": {
      "type": "string",
      "description": "The updated value to blacklist.",
      "example": "@blocked-domain.example"
    },
    "description": {
      "type": "string",
      "description": "The updated reason for this rule.",
      "example": "Block purchases from this email domain."
    }
  },
  "example": {
    "type": "WILDCARD_EMAIL",
    "data": "@blocked-domain.example",
    "description": "Block purchases from this email domain."
  }
}
```

Example:

```json
{
  "description": "Blocked after a verified fraud report."
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A blacklist rule that blocks purchases matching the provided details.",
      "required": [
        "id",
        "type",
        "data",
        "description",
        "created_at",
        "updated_at",
        "store_id"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "description": "Unique identifier for the blacklist rule.",
          "example": 1
        },
        "type": {
          "type": "string",
          "description": "The type of blacklist rule.",
          "enum": [
            "ASN",
            "COUNTRY",
            "EMAIL",
            "IP",
            "WILDCARD_EMAIL"
          ]
        },
        "data": {
          "type": "string",
          "description": "The data associated with the rule type, such as an IP address, email, or country code.",
          "example": "leo.martin@example.com"
        },
        "description": {
          "type": "string",
          "description": "Why this blacklist rule exists.",
          "example": "Block the address used by our launch-day load-test bot."
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was created.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was last updated.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "store_id": {
          "type": "integer",
          "description": "The store ID this blacklist rule belongs to.",
          "example": 1
        }
      }
    }
  },
  "example": {
    "data": {
      "id": 1,
      "type": "WILDCARD_EMAIL",
      "data": "@blocked.example",
      "description": "Retired after the growth experiment ended.",
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 42,
    "type": "EMAIL",
    "data": "blocked@example.com",
    "description": "Blocked after a verified fraud report.",
    "created_at": "2026-09-04T09:00:00Z",
    "updated_at": "2026-09-04T09:00:00Z",
    "store_id": 12
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# List All Blacklist Rules (/docs/api/blacklists/list-blacklists)

## GET /v2/blacklists

List blacklist rules

List store-scoped blacklist rules. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.blacklists.v2ListBlacklists();
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.blacklists.v2_list_blacklists()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->blacklists()->v2ListBlacklists();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    page := client.Blacklists().V2ListBlacklists(context.Background())
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Blacklists.V2ListBlacklistsAsync();
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.blacklists.v2ListBlacklists()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.blacklists.v2_list_blacklists
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::blacklists::V2ListBlacklistsParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2ListBlacklistsParams::default();
    let result = client.blacklists().v_2_list_blacklists(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Blacklists.v2_list_blacklists(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp blacklists v-2-list-blacklists

```

- Method: `GET`

- Path: `/v2/blacklists`

- Full URL: `https://sell.app/api/v2/blacklists`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `support:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/blacklists" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data",
    "links",
    "meta"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "description": "A blacklist rule that blocks purchases matching the provided details.",
        "required": [
          "id",
          "type",
          "data",
          "description",
          "created_at",
          "updated_at",
          "store_id"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "description": "Unique identifier for the blacklist rule.",
            "example": 1
          },
          "type": {
            "type": "string",
            "description": "The type of blacklist rule.",
            "enum": [
              "ASN",
              "COUNTRY",
              "EMAIL",
              "IP",
              "WILDCARD_EMAIL"
            ]
          },
          "data": {
            "type": "string",
            "description": "The data associated with the rule type, such as an IP address, email, or country code.",
            "example": "leo.martin@example.com"
          },
          "description": {
            "type": "string",
            "description": "Why this blacklist rule exists.",
            "example": "Block the address used by our launch-day load-test bot."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the blacklist rule was created.",
            "example": "2022-12-12T12:12:12.000000Z"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the blacklist rule was last updated.",
            "example": "2022-12-12T12:12:12.000000Z"
          },
          "store_id": {
            "type": "integer",
            "description": "The store ID this blacklist rule belongs to.",
            "example": 1
          }
        }
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  },
  "example": {
    "data": [
      {
        "id": 1,
        "type": "EMAIL",
        "data": "leo.martin@example.com",
        "description": "Block the address used by our launch-day load-test bot.",
        "created_at": "2022-12-12T12:12:12.000000Z",
        "updated_at": "2022-12-12T12:12:12.000000Z",
        "store_id": 1
      }
    ],
    "links": {
      "first": "https://sell.app/api/v1/blacklists?page=1",
      "last": "https://sell.app/api/v1/blacklists?page=4",
      "prev": null,
      "next": "https://sell.app/api/v1/blacklists?page=2"
    },
    "meta": {
      "current_page": 1,
      "from": 1,
      "last_page": 4,
      "path": "https://sell.app/api/v1/blacklists",
      "per_page": 15,
      "to": 15,
      "total": 57
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "id": 42,
      "type": "EMAIL",
      "data": "blocked@example.com",
      "description": "Blocked after a verified fraud report.",
      "created_at": "2026-09-04T09:00:00Z",
      "updated_at": "2026-09-04T09:00:00Z",
      "store_id": 12
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/blacklists?page=1",
    "last": "https://sell.app/api/v2/blacklists?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/blacklists",
    "per_page": 20,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/blacklists?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve a Blacklist Rule (/docs/api/blacklists/retrieve-blacklist)

## GET /v2/blacklists/{blacklist}

Retrieve a blacklist rule

Retrieve a blacklist rule in the selected store. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.blacklists.v2GetBlacklist({
  "blacklist": 42
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.blacklists.v2_get_blacklist(blacklist=42)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->blacklists()->v2GetBlacklist(blacklist: 42);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Blacklists().V2GetBlacklist(context.Background(), 42)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Blacklists.V2GetBlacklistAsync("42");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.blacklists.v2GetBlacklist(blacklist = "42")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.blacklists.v2_get_blacklist(blacklist: 42)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::blacklists::V2GetBlacklistParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2GetBlacklistParams::default();
    let result = client.blacklists().v_2_get_blacklist("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Blacklists.v2_get_blacklist(client, 42)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp blacklists v-2-get-blacklist 42

```

- Method: `GET`

- Path: `/v2/blacklists/{blacklist}`

- Full URL: `https://sell.app/api/v2/blacklists/{blacklist}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `support:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_BLACKLIST_ID='42'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/blacklists/${SELLAPP_BLACKLIST_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `blacklist` (`integer`, required): The blacklist identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A blacklist rule that blocks purchases matching the provided details.",
      "required": [
        "id",
        "type",
        "data",
        "description",
        "created_at",
        "updated_at",
        "store_id"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "description": "Unique identifier for the blacklist rule.",
          "example": 1
        },
        "type": {
          "type": "string",
          "description": "The type of blacklist rule.",
          "enum": [
            "ASN",
            "COUNTRY",
            "EMAIL",
            "IP",
            "WILDCARD_EMAIL"
          ]
        },
        "data": {
          "type": "string",
          "description": "The data associated with the rule type, such as an IP address, email, or country code.",
          "example": "leo.martin@example.com"
        },
        "description": {
          "type": "string",
          "description": "Why this blacklist rule exists.",
          "example": "Block the address used by our launch-day load-test bot."
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was created.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was last updated.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "store_id": {
          "type": "integer",
          "description": "The store ID this blacklist rule belongs to.",
          "example": 1
        }
      }
    }
  },
  "example": {
    "data": {
      "id": 1,
      "type": "WILDCARD_EMAIL",
      "data": "@blocked.example",
      "description": "Retired after the growth experiment ended.",
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 42,
    "type": "EMAIL",
    "data": "blocked@example.com",
    "description": "Blocked after a verified fraud report.",
    "created_at": "2026-09-04T09:00:00Z",
    "updated_at": "2026-09-04T09:00:00Z",
    "store_id": 12
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Update a Blacklist Rule (/docs/api/blacklists/update-blacklist)

## PATCH /v2/blacklists/{blacklist}

Update a blacklist rule

Update a blacklist rule in the selected store. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.blacklists.v2UpdateBlacklist({
  "blacklist": 42,
  "description": "Blocked after a verified fraud report."
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.blacklists.v2_update_blacklist(
    blacklist=42,
    description="Blocked after a verified fraud report."
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->blacklists()->v2UpdateBlacklist(
    blacklist: 42,
    description: 'Blocked after a verified fraud report.',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.BlacklistsV2UpdateBlacklistParams{}
    if err := json.Unmarshal([]byte("{\"description\":\"Blocked after a verified fraud report.\"}"), params); err != nil { panic(err) }
    result, err := client.Blacklists().V2UpdateBlacklist(context.Background(), 42, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Blacklists.V2UpdateBlacklistAsync(
    "42",
    new BlacklistsV2UpdateBlacklistOptions
    {
        Description = "Blocked after a verified fraud report.",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.blacklists.v2UpdateBlacklist(blacklist = "42", description = app.sell.sellapp.common.http.PatchField.Present("Blocked after a verified fraud report."))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.blacklists.v2_update_blacklist(
  blacklist: 42,
  description: "Blocked after a verified fraud report."
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::blacklists::V2UpdateBlacklistParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2UpdateBlacklistParams::new(serde_json::from_str("{\"description\":\"Blocked after a verified fraud report.\"}")?);
    let result = client.blacklists().v_2_update_blacklist("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Blacklists.v2_update_blacklist(client, 42, %{"description" => "Blocked after a verified fraud report."})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp blacklists v-2-update-blacklist 42 --description 'Blocked after a verified fraud report.' --yes

```

- Method: `PATCH`

- Path: `/v2/blacklists/{blacklist}`

- Full URL: `https://sell.app/api/v2/blacklists/{blacklist}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `support:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_BLACKLIST_ID='42'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/blacklists/${SELLAPP_BLACKLIST_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "description": "Blocked after a verified fraud report."
}'
```

## Path Parameters
- `blacklist` (`integer`, required): The blacklist identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, optional): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "description": "Provide one or more fields to update an existing blacklist rule.",
  "properties": {
    "type": {
      "type": "string",
      "description": "The type of blacklist rule.",
      "enum": [
        "ASN",
        "COUNTRY",
        "EMAIL",
        "IP",
        "WILDCARD_EMAIL"
      ]
    },
    "data": {
      "type": "string",
      "description": "The updated value to blacklist.",
      "example": "@blocked-domain.example"
    },
    "description": {
      "type": "string",
      "description": "The updated reason for this rule.",
      "example": "Block purchases from this email domain."
    }
  },
  "example": {
    "type": "WILDCARD_EMAIL",
    "data": "@blocked-domain.example",
    "description": "Block purchases from this email domain."
  }
}
```

Example:

```json
{
  "description": "Blocked after a verified fraud report."
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A blacklist rule that blocks purchases matching the provided details.",
      "required": [
        "id",
        "type",
        "data",
        "description",
        "created_at",
        "updated_at",
        "store_id"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "description": "Unique identifier for the blacklist rule.",
          "example": 1
        },
        "type": {
          "type": "string",
          "description": "The type of blacklist rule.",
          "enum": [
            "ASN",
            "COUNTRY",
            "EMAIL",
            "IP",
            "WILDCARD_EMAIL"
          ]
        },
        "data": {
          "type": "string",
          "description": "The data associated with the rule type, such as an IP address, email, or country code.",
          "example": "leo.martin@example.com"
        },
        "description": {
          "type": "string",
          "description": "Why this blacklist rule exists.",
          "example": "Block the address used by our launch-day load-test bot."
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was created.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "description": "When the blacklist rule was last updated.",
          "example": "2022-12-12T12:12:12.000000Z"
        },
        "store_id": {
          "type": "integer",
          "description": "The store ID this blacklist rule belongs to.",
          "example": 1
        }
      }
    }
  },
  "example": {
    "data": {
      "id": 1,
      "type": "WILDCARD_EMAIL",
      "data": "@blocked.example",
      "description": "Retired after the growth experiment ended.",
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 42,
    "type": "EMAIL",
    "data": "blocked@example.com",
    "description": "Blocked after a verified fraud report.",
    "created_at": "2026-09-04T09:00:00Z",
    "updated_at": "2026-09-04T09:00:00Z",
    "store_id": 12
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Overview (/docs/api/bookings)



Use booking APIs to decide when customers can book and to manage appointments afterward. They follow the same rules as the seller dashboard. Your key needs the `listing` ability to configure availability and date overrides, or `invoice` to read, cancel, and reschedule customer appointments.

All resources are scoped to the store selected by `X-STORE`. Product, variant, booking, and provider-connection IDs from another store return an authorization or not-found response rather than crossing store boundaries.

## Endpoints [#endpoints]

* [List appointments](/api/bookings/list-appointments)
* [Search appointments](/api/bookings/search-appointments)
* [Retrieve an appointment](/api/bookings/retrieve-an-appointment)
* [Update an appointment](/api/bookings/update-an-appointment)
* [Retrieve booking configuration](/api/bookings/retrieve-booking-configuration)
* [Update booking configuration](/api/bookings/update-booking-configuration)
* [List booking date overrides](/api/bookings/list-booking-date-overrides)
* [Set booking date availability](/api/bookings/set-booking-date-availability)

## Time and concurrency [#time-and-concurrency]

Appointment times are returned as ISO 8601 timestamps. Weekly availability and date overrides use an IANA `timezone`, such as `Europe/London`. A local date can span 23 or 25 hours when daylight saving time changes; SellApp stores the corresponding UTC boundaries.

Rescheduling and checkout holds share the same product- or variant-level lock, so they cannot reserve conflicting slots at the same time. SellApp checks availability again while holding that lock. An outdated request cannot overwrite a cancelled appointment or take a slot already held by another appointment.

## Webhooks [#webhooks]

Appointment changes can be observed by enabling the public events `booking.cancelled` and `booking.rescheduled` on a webhook channel. Payloads contain safe appointment state and omit provider error details and credentials.


# List appointments (/docs/api/bookings/list-appointments)

Returns appointments in descending start-time order. The response includes
the purchase and line-item identifiers so you can look up what was booked.

## GET /v2/bookings

List appointments

List appointments for the selected store. Requires the `invoice` Sanctum ability and invoice permission. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.bookings.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.bookings.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->bookings()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.BookingsListParams{}
    page := client.Bookings().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Bookings.ListAsync(new BookingsListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.bookings.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.bookings.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::bookings::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.bookings().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Bookings.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp bookings list

```

- Method: `GET`

- Path: `/v2/bookings`

- Full URL: `https://sell.app/api/v2/bookings`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/bookings" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching items in one data array without pagination links or metadata.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "product_id": {
                "type": "integer"
              },
              "product_variant_id": {
                "type": "integer"
              },
              "order_id": {
                "type": "integer"
              },
              "invoice_id": {
                "type": "integer"
              },
              "customer_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "customer_email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "slot_start_at": {
                "type": "string",
                "format": "date-time"
              },
              "slot_end_at": {
                "type": "string",
                "format": "date-time"
              },
              "timezone": {
                "type": "string",
                "example": "Europe/London"
              },
              "quantity": {
                "type": "integer",
                "minimum": 1
              },
              "status": {
                "type": "string",
                "enum": [
                  "pending",
                  "confirmed",
                  "cancelled",
                  "needs_reschedule",
                  "failed"
                ]
              },
              "calendar_sync_status": {
                "type": "string",
                "enum": [
                  "pending",
                  "synced",
                  "skipped",
                  "cancelled",
                  "failed"
                ]
              },
              "external_event_link": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "Calendar event URL. Always null after cancellation."
              },
              "video_join_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "Video meeting URL. Always null after cancellation."
              },
              "confirmed_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "cancelled_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "product": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "title": {
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "variant": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "title": {
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "id",
              "product_id",
              "product_variant_id",
              "order_id",
              "invoice_id",
              "customer_id",
              "customer_email",
              "slot_start_at",
              "slot_end_at",
              "timezone",
              "quantity",
              "status",
              "calendar_sync_status",
              "external_event_link",
              "video_join_url",
              "confirmed_at",
              "cancelled_at",
              "created_at",
              "updated_at",
              "product",
              "variant"
            ]
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "product_id": {
                "type": "integer"
              },
              "product_variant_id": {
                "type": "integer"
              },
              "order_id": {
                "type": "integer"
              },
              "invoice_id": {
                "type": "integer"
              },
              "customer_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "customer_email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "slot_start_at": {
                "type": "string",
                "format": "date-time"
              },
              "slot_end_at": {
                "type": "string",
                "format": "date-time"
              },
              "timezone": {
                "type": "string",
                "example": "Europe/London"
              },
              "quantity": {
                "type": "integer",
                "minimum": 1
              },
              "status": {
                "type": "string",
                "enum": [
                  "pending",
                  "confirmed",
                  "cancelled",
                  "needs_reschedule",
                  "failed"
                ]
              },
              "calendar_sync_status": {
                "type": "string",
                "enum": [
                  "pending",
                  "synced",
                  "skipped",
                  "cancelled",
                  "failed"
                ]
              },
              "external_event_link": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "Calendar event URL. Always null after cancellation."
              },
              "video_join_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "Video meeting URL. Always null after cancellation."
              },
              "confirmed_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "cancelled_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "product": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "title": {
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "variant": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "title": {
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "id",
              "product_id",
              "product_variant_id",
              "order_id",
              "invoice_id",
              "customer_id",
              "customer_email",
              "slot_start_at",
              "slot_end_at",
              "timezone",
              "quantity",
              "status",
              "calendar_sync_status",
              "external_event_link",
              "video_join_url",
              "confirmed_at",
              "cancelled_at",
              "created_at",
              "updated_at",
              "product",
              "variant"
            ]
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": "018f61d6-1c46-7b42-8a94-522bc6b5c53f",
      "product_id": 41,
      "product_variant_id": 73,
      "order_id": 501,
      "invoice_id": 901,
      "customer_id": 301,
      "customer_email": "isabel.torres@example.com",
      "slot_start_at": "2028-03-26T09:00:00Z",
      "slot_end_at": "2028-03-26T09:30:00Z",
      "timezone": "Europe/London",
      "quantity": 1,
      "status": "confirmed",
      "calendar_sync_status": "synced",
      "external_event_link": "https://calendar.google.com/calendar/event?eid=example",
      "video_join_url": "https://meet.google.com/abc-defg-hij",
      "confirmed_at": "2028-03-01T12:00:00Z",
      "cancelled_at": null,
      "created_at": "2028-03-01T11:59:00Z",
      "updated_at": "2028-03-01T12:00:00Z",
      "product": {
        "id": 41,
        "title": "Canva deck intervention"
      },
      "variant": {
        "id": 73,
        "title": "Thirty slides or thirty minutes"
      }
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/bookings?page=1",
    "last": "https://sell.app/api/v2/bookings?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/bookings",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/bookings?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# List booking date overrides (/docs/api/bookings/list-booking-date-overrides)

Use `product_variant_id` to select one same-store booking variant. Without it, the endpoint returns all date overrides for the selected store, including global and variant-specific entries.

Set `pagination=false` to return at most 100 matching overrides in one `data`
array without pagination links or metadata. Paginated responses default to 15
overrides per page.

## GET /v2/booking-calendar-events

List booking date overrides

List store-wide or variant-specific booking date overrides. Date boundaries are stored in UTC and interpreted in the booking timezone. Requires the `listing` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.bookingsCalendarEvents.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.bookings_calendar_events.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->bookingsCalendarEvents()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.BookingsCalendarEventsListParams{}
    page := client.BookingsCalendarEvents().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.BookingsCalendarEvents.ListAsync(new BookingsCalendarEventsListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.bookingsCalendarEvents.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.bookings_calendar_events.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::bookings_calendar_events::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.bookings_calendar_events().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.BookingsCalendarEvents.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp bookings calendar-events list

```

- Method: `GET`

- Path: `/v2/booking-calendar-events`

- Full URL: `https://sell.app/api/v2/booking-calendar-events`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/booking-calendar-events" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `product_variant_id` (`integer`, optional): Return the effective override hierarchy for a same-store booking variant, including inherited store-wide and product-wide rows plus exact variant rows.
- `from` (`string`, format `date-time`, optional): Only return overrides ending after this instant.
- `to` (`string`, format `date-time`, optional): Only return overrides starting before this instant.
- `status` (`string`, optional): Filter by override status.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching overrides in one data array without pagination links or metadata.
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "product_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "product_variant_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "type": {
                "type": "string",
                "enum": [
                  "blocked",
                  "available"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "active",
                  "inactive"
                ]
              },
              "title": {
                "type": "string"
              },
              "slot_start_at": {
                "type": "string",
                "format": "date-time"
              },
              "slot_end_at": {
                "type": "string",
                "format": "date-time"
              },
              "timezone": {
                "type": "string"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "product_id",
              "product_variant_id",
              "type",
              "status",
              "title",
              "slot_start_at",
              "slot_end_at",
              "timezone",
              "created_at",
              "updated_at"
            ]
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "product_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "product_variant_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "type": {
                "type": "string",
                "enum": [
                  "blocked",
                  "available"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "active",
                  "inactive"
                ]
              },
              "title": {
                "type": "string"
              },
              "slot_start_at": {
                "type": "string",
                "format": "date-time"
              },
              "slot_end_at": {
                "type": "string",
                "format": "date-time"
              },
              "timezone": {
                "type": "string"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "product_id",
              "product_variant_id",
              "type",
              "status",
              "title",
              "slot_start_at",
              "slot_end_at",
              "timezone",
              "created_at",
              "updated_at"
            ]
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example (minimal):

```json
{
  "data": [
    {
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "product_id": 120,
      "product_variant_id": 4321,
      "type": "blocked",
      "status": "active",
      "title": "Unavailable date",
      "slot_start_at": "2026-09-15T00:00:00Z",
      "slot_end_at": "2026-09-16T00:00:00Z",
      "timezone": "UTC",
      "created_at": "2026-09-01T12:00:00Z",
      "updated_at": "2026-09-01T12:00:00Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/booking-calendar-events?page=1",
    "last": "https://sell.app/api/v2/booking-calendar-events?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/booking-calendar-events?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ],
    "path": "https://sell.app/api/v2/booking-calendar-events",
    "per_page": 50,
    "to": 1,
    "total": 1
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve an appointment (/docs/api/bookings/retrieve-an-appointment)

Provider synchronization status is returned, but raw provider error messages and credentials are not exposed.

## GET /v2/bookings/{booking}

Retrieve an appointment

Retrieve a store-scoped appointment by UUID or numeric ID. Provider error details are intentionally not exposed. Requires the `invoice` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.bookings.get({
  "booking": "018f61d6-1c46-7b42-8a94-522bc6b5c53f"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.bookings.get(booking="018f61d6-1c46-7b42-8a94-522bc6b5c53f")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->bookings()->get(booking: '018f61d6-1c46-7b42-8a94-522bc6b5c53f');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Bookings().Get(context.Background(), "018f61d6-1c46-7b42-8a94-522bc6b5c53f")
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Bookings.GetAsync("018f61d6-1c46-7b42-8a94-522bc6b5c53f");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.bookings.get(booking = "018f61d6-1c46-7b42-8a94-522bc6b5c53f")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.bookings.get(booking: "018f61d6-1c46-7b42-8a94-522bc6b5c53f")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::bookings::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.bookings().get("018f61d6-1c46-7b42-8a94-522bc6b5c53f", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Bookings.get(client, "018f61d6-1c46-7b42-8a94-522bc6b5c53f")
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp bookings get 018f61d6-1c46-7b42-8a94-522bc6b5c53f

```

- Method: `GET`

- Path: `/v2/bookings/{booking}`

- Full URL: `https://sell.app/api/v2/bookings/{booking}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_BOOKING_ID='018f61d6-1c46-7b42-8a94-522bc6b5c53f'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/bookings/${SELLAPP_BOOKING_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `booking` (`string`, required): The appointment UUID or numeric ID.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "product_id": {
          "type": "integer"
        },
        "product_variant_id": {
          "type": "integer"
        },
        "order_id": {
          "type": "integer"
        },
        "invoice_id": {
          "type": "integer"
        },
        "customer_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "customer_email": {
          "type": [
            "string",
            "null"
          ],
          "format": "email"
        },
        "slot_start_at": {
          "type": "string",
          "format": "date-time"
        },
        "slot_end_at": {
          "type": "string",
          "format": "date-time"
        },
        "timezone": {
          "type": "string",
          "example": "Europe/London"
        },
        "quantity": {
          "type": "integer",
          "minimum": 1
        },
        "status": {
          "type": "string",
          "enum": [
            "pending",
            "confirmed",
            "cancelled",
            "needs_reschedule",
            "failed"
          ]
        },
        "calendar_sync_status": {
          "type": "string",
          "enum": [
            "pending",
            "synced",
            "skipped",
            "cancelled",
            "failed"
          ]
        },
        "external_event_link": {
          "type": [
            "string",
            "null"
          ],
          "format": "uri",
          "description": "Calendar event URL. Always null after cancellation."
        },
        "video_join_url": {
          "type": [
            "string",
            "null"
          ],
          "format": "uri",
          "description": "Video meeting URL. Always null after cancellation."
        },
        "confirmed_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "cancelled_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "product": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "id": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "title": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "variant": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "id": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "title": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "required": [
        "id",
        "product_id",
        "product_variant_id",
        "order_id",
        "invoice_id",
        "customer_id",
        "customer_email",
        "slot_start_at",
        "slot_end_at",
        "timezone",
        "quantity",
        "status",
        "calendar_sync_status",
        "external_event_link",
        "video_join_url",
        "confirmed_at",
        "cancelled_at",
        "created_at",
        "updated_at",
        "product",
        "variant"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": "018f61d6-1c46-7b42-8a94-522bc6b5c53f",
    "product_id": 41,
    "product_variant_id": 73,
    "order_id": 501,
    "invoice_id": 901,
    "customer_id": 301,
    "customer_email": "isabel.torres@example.com",
    "slot_start_at": "2028-03-26T09:00:00Z",
    "slot_end_at": "2028-03-26T09:30:00Z",
    "timezone": "Europe/London",
    "quantity": 1,
    "status": "confirmed",
    "calendar_sync_status": "synced",
    "external_event_link": "https://calendar.google.com/calendar/event?eid=example",
    "video_join_url": "https://meet.google.com/abc-defg-hij",
    "confirmed_at": "2028-03-01T12:00:00Z",
    "cancelled_at": null,
    "created_at": "2028-03-01T11:59:00Z",
    "updated_at": "2028-03-01T12:00:00Z",
    "product": {
      "id": 41,
      "title": "Canva deck intervention"
    },
    "variant": {
      "id": 73,
      "title": "Thirty slides or thirty minutes"
    }
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve booking configuration (/docs/api/bookings/retrieve-booking-configuration)

Returns weekly availability, duration, capacity, notice windows, conflict scope, calendar connection references, meeting behavior, and reminders. Provider credentials are never returned.

## GET /v2/products/{product}/variants/{variant}/booking

Retrieve booking configuration

Retrieve creator-facing availability, capacity, calendar, meeting, and reminder configuration for a booking variant. Requires the `listing` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.productVariantsBooking.get({
  "product": "41",
  "variant": 73
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.product_variants_booking.get(
    product="41",
    variant=73
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->productVariantsBooking()->get(
    product: '41',
    variant: 73,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.ProductVariantsBooking().Get(context.Background(), "41", 73)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.ProductVariantsBooking.GetAsync(
    "41",
    "73"
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.productVariantsBooking.get(product = "41", variant = "73")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.product_variants_booking.get(
  product: "41",
  variant: 73
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::product_variants_booking::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.product_variants_booking().get("41", "73", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.ProductVariantsBooking.get(client, "41", 73)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp product-variants booking get --product 41 73

```

- Method: `GET`

- Path: `/v2/products/{product}/variants/{variant}/booking`

- Full URL: `https://sell.app/api/v2/products/{product}/variants/{variant}/booking`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_ID='41'
export SELLAPP_VARIANT_ID='73'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/products/${SELLAPP_PRODUCT_ID}/variants/${SELLAPP_VARIANT_ID}/booking" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `product` (`string`, required): The booking product ID or slug.
- `variant` (`integer`, required): The variant path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "product_id": {
          "type": "integer",
          "readOnly": true
        },
        "product_variant_id": {
          "type": "integer",
          "readOnly": true
        },
        "mode": {
          "type": "string",
          "enum": [
            "native"
          ]
        },
        "conflict_scope": {
          "type": "string",
          "enum": [
            "product",
            "variant"
          ]
        },
        "timezone": {
          "type": "string",
          "example": "America/New_York"
        },
        "duration_minutes": {
          "type": "integer",
          "minimum": 30,
          "multipleOf": 30
        },
        "capacity_per_slot": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000
        },
        "min_notice_minutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 525600
        },
        "max_advance_days": {
          "type": "integer",
          "minimum": 1,
          "maximum": 730
        },
        "buffer_before_minutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1440,
          "multipleOf": 30
        },
        "buffer_after_minutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1440,
          "multipleOf": 30
        },
        "availability": {
          "type": "array",
          "minItems": 7,
          "maxItems": 7,
          "items": {
            "type": "object",
            "properties": {
              "day": {
                "type": "integer",
                "minimum": 1,
                "maximum": 7
              },
              "enabled": {
                "type": "boolean"
              },
              "start": {
                "type": "string",
                "example": "09:00"
              },
              "end": {
                "type": "string",
                "example": "17:00"
              }
            },
            "required": [
              "day",
              "enabled",
              "start",
              "end"
            ]
          }
        },
        "provider_connection_ids": {
          "type": "array",
          "items": {
            "type": "integer"
          }
        },
        "video_provider": {
          "type": "string",
          "enum": [
            "none",
            "google_meet",
            "zoom"
          ]
        },
        "video_provider_connection_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "reminders_enabled": {
          "type": "boolean"
        },
        "reminder_offset_value": {
          "type": "integer",
          "minimum": 1,
          "maximum": 10080
        },
        "reminder_offset_unit": {
          "type": "string",
          "enum": [
            "minutes",
            "hours",
            "days",
            "weeks"
          ]
        },
        "meta": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": true
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "required": [
        "product_id",
        "product_variant_id",
        "mode",
        "conflict_scope",
        "timezone",
        "duration_minutes",
        "capacity_per_slot",
        "min_notice_minutes",
        "max_advance_days",
        "buffer_before_minutes",
        "buffer_after_minutes",
        "availability",
        "provider_connection_ids",
        "video_provider",
        "video_provider_connection_id",
        "reminders_enabled",
        "reminder_offset_value",
        "reminder_offset_unit",
        "meta"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "product_id": 41,
    "product_variant_id": 73,
    "mode": "native",
    "conflict_scope": "variant",
    "timezone": "Europe/London",
    "duration_minutes": 60,
    "capacity_per_slot": 1,
    "min_notice_minutes": 1440,
    "max_advance_days": 60,
    "buffer_before_minutes": 0,
    "buffer_after_minutes": 0,
    "availability": [
      {
        "day": 1,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 2,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 3,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 4,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 5,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 6,
        "enabled": false,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 7,
        "enabled": false,
        "start": "09:00",
        "end": "17:00"
      }
    ],
    "provider_connection_ids": [],
    "video_provider": "none",
    "video_provider_connection_id": null,
    "reminders_enabled": false,
    "reminder_offset_value": 1,
    "reminder_offset_unit": "hours",
    "meta": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Search appointments (/docs/api/bookings/search-appointments)

Search by appointment UUID or customer email. Supported filters include product, variant, order, customer, appointment status, and calendar sync status.

## POST /v2/bookings/search

Search appointments

Search appointment UUIDs or customer email addresses and compose store-scoped filters and sorting. The public `id` filter targets the UUID returned as `id`; `uuid` remains an equivalent compatibility filter. Requires the `invoice` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.bookings.search({
  "filters": [{"field": "id", "operator": "=", "value": "018f61d6-1c46-7b42-8a94-522bc6b5c53f"}],
  "sort": [{"field": "created_at", "direction": "desc"}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.bookings.search(
    filters=[
        {
            "field": "id",
            "operator": "=",
            "value": "018f61d6-1c46-7b42-8a94-522bc6b5c53f"
        }
    ],
    sort=[{"field": "created_at", "direction": "desc"}]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->bookings()->search(
    filters: [
        [
            'field' => 'id',
            'operator' => '=',
            'value' => '018f61d6-1c46-7b42-8a94-522bc6b5c53f',
        ],
    ],
    sort: [['field' => 'created_at', 'direction' => 'desc']],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.BookingsSearchParams{}
    if err := json.Unmarshal([]byte("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":\"018f61d6-1c46-7b42-8a94-522bc6b5c53f\"}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}"), params); err != nil { panic(err) }
    page := client.Bookings().Search(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Bookings.SearchAsync(new BookingsSearchOptions
    {
        Filters = JsonConvert.DeserializeObject<List<SearchAppointmentsRequestApplicationJsonPropertyFiltersItem>>("[{\"field\":\"id\",\"operator\":\"=\",\"value\":\"018f61d6-1c46-7b42-8a94-522bc6b5c53f\"}]")!,
        Sort = JsonConvert.DeserializeObject<List<SearchAppointmentsRequestApplicationJsonPropertySortItem>>("[{\"field\":\"created_at\",\"direction\":\"desc\"}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.bookings.search(filters = listOf(ObjectMapperFactory.read("{\"field\":\"id\",\"operator\":\"=\",\"value\":\"018f61d6-1c46-7b42-8a94-522bc6b5c53f\"}", app.sell.sellapp.models.SearchAppointmentsRequestApplicationJsonPropertyFiltersItem::class.java)), sort = listOf(ObjectMapperFactory.read("{\"field\":\"created_at\",\"direction\":\"desc\"}", app.sell.sellapp.models.SearchAppointmentsRequestApplicationJsonPropertySortItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.bookings.search(
  filters: [{ field: "id", operator: "=", value: "018f61d6-1c46-7b42-8a94-522bc6b5c53f" }],
  sort: [{ field: "created_at", direction: "desc" }]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::bookings::SearchParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = SearchParams::new(serde_json::from_str("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":\"018f61d6-1c46-7b42-8a94-522bc6b5c53f\"}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}")?);
    let result = client.bookings().search(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Bookings.search(client, %{"filters" => [%{"field" => "id", "operator" => "=", "value" => "018f61d6-1c46-7b42-8a94-522bc6b5c53f"}], "sort" => [%{"field" => "created_at", "direction" => "desc"}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp bookings search --body '{"filters":[{"field":"id","operator":"=","value":"018f61d6-1c46-7b42-8a94-522bc6b5c53f"}],"sort":[{"field":"created_at","direction":"desc"}]}'

```

- Method: `POST`

- Path: `/v2/bookings/search`

- Full URL: `https://sell.app/api/v2/bookings/search`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/bookings/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": "018f61d6-1c46-7b42-8a94-522bc6b5c53f"
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching items in one data array without pagination links or metadata.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "operator": {
            "type": "string",
            "default": "="
          },
          "value": {},
          "type": {
            "type": "string",
            "enum": [
              "and",
              "or"
            ],
            "default": "and"
          },
          "nested": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "anyOf": [
          {
            "required": [
              "field"
            ]
          },
          {
            "required": [
              "nested"
            ]
          }
        ]
      }
    },
    "sort": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "default": "asc"
          }
        },
        "required": [
          "field"
        ]
      }
    },
    "search": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "null"
          ]
        },
        "case_sensitive": {
          "type": "boolean"
        }
      }
    },
    "includes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "relation": {
            "type": "string"
          }
        },
        "required": [
          "relation"
        ]
      }
    }
  }
}
```

Example:

```json
{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": "018f61d6-1c46-7b42-8a94-522bc6b5c53f"
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "product_id": {
                "type": "integer"
              },
              "product_variant_id": {
                "type": "integer"
              },
              "order_id": {
                "type": "integer"
              },
              "invoice_id": {
                "type": "integer"
              },
              "customer_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "customer_email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "slot_start_at": {
                "type": "string",
                "format": "date-time"
              },
              "slot_end_at": {
                "type": "string",
                "format": "date-time"
              },
              "timezone": {
                "type": "string",
                "example": "Europe/London"
              },
              "quantity": {
                "type": "integer",
                "minimum": 1
              },
              "status": {
                "type": "string",
                "enum": [
                  "pending",
                  "confirmed",
                  "cancelled",
                  "needs_reschedule",
                  "failed"
                ]
              },
              "calendar_sync_status": {
                "type": "string",
                "enum": [
                  "pending",
                  "synced",
                  "skipped",
                  "cancelled",
                  "failed"
                ]
              },
              "external_event_link": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "Calendar event URL. Always null after cancellation."
              },
              "video_join_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "Video meeting URL. Always null after cancellation."
              },
              "confirmed_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "cancelled_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "product": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "title": {
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "variant": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "title": {
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "id",
              "product_id",
              "product_variant_id",
              "order_id",
              "invoice_id",
              "customer_id",
              "customer_email",
              "slot_start_at",
              "slot_end_at",
              "timezone",
              "quantity",
              "status",
              "calendar_sync_status",
              "external_event_link",
              "video_join_url",
              "confirmed_at",
              "cancelled_at",
              "created_at",
              "updated_at",
              "product",
              "variant"
            ]
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "product_id": {
                "type": "integer"
              },
              "product_variant_id": {
                "type": "integer"
              },
              "order_id": {
                "type": "integer"
              },
              "invoice_id": {
                "type": "integer"
              },
              "customer_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "customer_email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "slot_start_at": {
                "type": "string",
                "format": "date-time"
              },
              "slot_end_at": {
                "type": "string",
                "format": "date-time"
              },
              "timezone": {
                "type": "string",
                "example": "Europe/London"
              },
              "quantity": {
                "type": "integer",
                "minimum": 1
              },
              "status": {
                "type": "string",
                "enum": [
                  "pending",
                  "confirmed",
                  "cancelled",
                  "needs_reschedule",
                  "failed"
                ]
              },
              "calendar_sync_status": {
                "type": "string",
                "enum": [
                  "pending",
                  "synced",
                  "skipped",
                  "cancelled",
                  "failed"
                ]
              },
              "external_event_link": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "Calendar event URL. Always null after cancellation."
              },
              "video_join_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "Video meeting URL. Always null after cancellation."
              },
              "confirmed_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "cancelled_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "product": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "title": {
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "variant": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "title": {
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "id",
              "product_id",
              "product_variant_id",
              "order_id",
              "invoice_id",
              "customer_id",
              "customer_email",
              "slot_start_at",
              "slot_end_at",
              "timezone",
              "quantity",
              "status",
              "calendar_sync_status",
              "external_event_link",
              "video_join_url",
              "confirmed_at",
              "cancelled_at",
              "created_at",
              "updated_at",
              "product",
              "variant"
            ]
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": "018f61d6-1c46-7b42-8a94-522bc6b5c53f",
      "product_id": 41,
      "product_variant_id": 73,
      "order_id": 501,
      "invoice_id": 901,
      "customer_id": 301,
      "customer_email": "isabel.torres@example.com",
      "slot_start_at": "2028-03-26T09:00:00Z",
      "slot_end_at": "2028-03-26T09:30:00Z",
      "timezone": "Europe/London",
      "quantity": 1,
      "status": "confirmed",
      "calendar_sync_status": "synced",
      "external_event_link": "https://calendar.google.com/calendar/event?eid=example",
      "video_join_url": "https://meet.google.com/abc-defg-hij",
      "confirmed_at": "2028-03-01T12:00:00Z",
      "cancelled_at": null,
      "created_at": "2028-03-01T11:59:00Z",
      "updated_at": "2028-03-01T12:00:00Z",
      "product": {
        "id": 41,
        "title": "Canva deck intervention"
      },
      "variant": {
        "id": 73,
        "title": "Thirty slides or thirty minutes"
      }
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/bookings/search?page=1",
    "last": "https://sell.app/api/v2/bookings/search?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/bookings/search",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/bookings/search?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Set booking date availability (/docs/api/bookings/set-booking-date-availability)

Send `available: false` to block the dates. Send `available: true` to clear the exact block. For a variant inheriting a store-wide block, `available: true` creates an explicit variant override.

## POST /v2/booking-calendar-events

Set booking date availability

Atomically mark one or more local calendar dates unavailable or available for the store or one same-store booking variant. Requires the `listing` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.bookingsCalendarEvents.set({
  "productVariantId": 73,
  "dates": ["2028-03-26", "2028-03-27"],
  "available": false
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.bookings_calendar_events.set(
    product_variant_id=73,
    dates=["2028-03-26", "2028-03-27"],
    available=False
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->bookingsCalendarEvents()->set(
    productVariantId: 73,
    dates: ['2028-03-26', '2028-03-27'],
    available: false,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.BookingsCalendarEventsSetParams{}
    if err := json.Unmarshal([]byte("{\"product_variant_id\":73,\"dates\":[\"2028-03-26\",\"2028-03-27\"],\"available\":false}"), params); err != nil { panic(err) }
    result, err := client.BookingsCalendarEvents().Set(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.BookingsCalendarEvents.SetAsync(new BookingsCalendarEventsSetOptions
    {
        ProductVariantId = JsonConvert.DeserializeObject<long?>("73")!,
        Dates = JsonConvert.DeserializeObject<List<string>>("[\"2028-03-26\",\"2028-03-27\"]")!,
        Available = false,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.bookingsCalendarEvents.set(productVariantId = 73L, dates = listOf("2028-03-26", "2028-03-27"), available = false)
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.bookings_calendar_events.set(
  product_variant_id: 73,
  dates: ["2028-03-26", "2028-03-27"],
  available: false
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::bookings_calendar_events::SetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = SetParams::new(serde_json::from_str("{\"product_variant_id\":73,\"dates\":[\"2028-03-26\",\"2028-03-27\"],\"available\":false}")?);
    let result = client.bookings_calendar_events().set(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.BookingsCalendarEvents.set(client, %{"product_variant_id" => 73, "dates" => ["2028-03-26", "2028-03-27"], "available" => false})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp bookings calendar-events set --body '{"product_variant_id":73,"dates":["2028-03-26","2028-03-27"],"available":false}' --yes

```

- Method: `POST`

- Path: `/v2/booking-calendar-events`

- Full URL: `https://sell.app/api/v2/booking-calendar-events`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/booking-calendar-events" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "product_variant_id": 73,
  "dates": [
    "2028-03-26",
    "2028-03-27"
  ],
  "available": false
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "product_variant_id": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "dates": {
      "type": "array",
      "minItems": 1,
      "maxItems": 366,
      "uniqueItems": true,
      "items": {
        "type": "string",
        "format": "date"
      }
    },
    "available": {
      "type": "boolean",
      "description": "Set false to block the dates and true to clear the exact block or open an inherited block for the variant."
    }
  },
  "required": [
    "dates",
    "available"
  ]
}
```

Example:

```json
{
  "product_variant_id": 73,
  "dates": [
    "2028-03-26",
    "2028-03-27"
  ],
  "available": false
}
```

## Responses

### 201

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "product_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "product_variant_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "blocked",
              "available"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ]
          },
          "title": {
            "type": "string"
          },
          "slot_start_at": {
            "type": "string",
            "format": "date-time"
          },
          "slot_end_at": {
            "type": "string",
            "format": "date-time"
          },
          "timezone": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "product_id",
          "product_variant_id",
          "type",
          "status",
          "title",
          "slot_start_at",
          "slot_end_at",
          "timezone",
          "created_at",
          "updated_at"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": "01992a65-e064-71ba-b38f-902b7966a6b1",
      "product_id": 41,
      "product_variant_id": 73,
      "type": "blocked",
      "status": "active",
      "title": "Unavailable date",
      "timezone": "Europe/London",
      "slot_start_at": "2028-03-26T00:00:00Z",
      "slot_end_at": "2028-03-26T23:00:00Z",
      "created_at": "2026-08-30T12:00:01.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z"
    },
    {
      "id": "01992a65-e064-71ba-b38f-902b7966a6b2",
      "product_id": 41,
      "product_variant_id": 73,
      "type": "blocked",
      "status": "active",
      "title": "Unavailable date",
      "timezone": "Europe/London",
      "slot_start_at": "2028-03-26T23:00:00Z",
      "slot_end_at": "2028-03-27T23:00:00Z",
      "created_at": "2026-08-30T12:00:01.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z"
    }
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Update an appointment (/docs/api/bookings/update-an-appointment)

Patch the appointment with a future `slot_start_at` to reschedule it. To cancel it, patch the dedicated status endpoint with `status: "cancelled"`. Rescheduling rechecks availability and refuses stale or conflicting changes.

## PATCH /v2/bookings/{booking}

Update an appointment

Reschedule an appointment atomically. Current availability is verified under the same conflict lock used by checkout holds. Requires the `invoice` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.bookings.update({
  "booking": "018f61d6-1c46-7b42-8a94-522bc6b5c53f",
  "slotStartAt": new Date("2028-03-27T10:00:00+01:00"),
  "timezone": "Europe/London"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.bookings.update(
    booking="018f61d6-1c46-7b42-8a94-522bc6b5c53f",
    slot_start_at="2028-03-27T10:00:00+01:00",
    timezone="Europe/London"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->bookings()->update(
    booking: '018f61d6-1c46-7b42-8a94-522bc6b5c53f',
    slotStartAt: '2028-03-27T10:00:00+01:00',
    timezone: 'Europe/London',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.BookingsUpdateParams{}
    if err := json.Unmarshal([]byte("{\"slot_start_at\":\"2028-03-27T10:00:00+01:00\",\"timezone\":\"Europe/London\"}"), params); err != nil { panic(err) }
    result, err := client.Bookings().Update(context.Background(), "018f61d6-1c46-7b42-8a94-522bc6b5c53f", params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Bookings.UpdateAsync(
    "018f61d6-1c46-7b42-8a94-522bc6b5c53f",
    new BookingsUpdateOptions
    {
        SlotStartAt = JsonConvert.DeserializeObject<DateTimeOffset>("\"2028-03-27T10:00:00+01:00\"")!,
        Timezone = JsonConvert.DeserializeObject<string?>("\"Europe/London\"")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.bookings.update(booking = "018f61d6-1c46-7b42-8a94-522bc6b5c53f", slotStartAt = java.time.OffsetDateTime.parse("2028-03-27T10:00:00+01:00"), timezone = app.sell.sellapp.common.http.PatchField.Present("Europe/London"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.bookings.update(
  booking: "018f61d6-1c46-7b42-8a94-522bc6b5c53f",
  slot_start_at: "2028-03-27T10:00:00+01:00",
  timezone: "Europe/London"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::bookings::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{\"slot_start_at\":\"2028-03-27T10:00:00+01:00\",\"timezone\":\"Europe/London\"}")?);
    let result = client.bookings().update("018f61d6-1c46-7b42-8a94-522bc6b5c53f", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Bookings.update(client, "018f61d6-1c46-7b42-8a94-522bc6b5c53f", %{"slot_start_at" => "2028-03-27T10:00:00+01:00", "timezone" => "Europe/London"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp bookings update 018f61d6-1c46-7b42-8a94-522bc6b5c53f --slot-start-at '2028-03-27T10:00:00+01:00' --timezone Europe/London --yes

```

- Method: `PATCH`

- Path: `/v2/bookings/{booking}`

- Full URL: `https://sell.app/api/v2/bookings/{booking}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_BOOKING_ID='018f61d6-1c46-7b42-8a94-522bc6b5c53f'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/bookings/${SELLAPP_BOOKING_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "slot_start_at": "2028-03-27T10:00:00+01:00",
  "timezone": "Europe/London"
}'
```

## Path Parameters
- `booking` (`string`, required): The appointment UUID or numeric ID.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "slot_start_at": {
      "type": "string",
      "format": "date-time",
      "description": "A future slot start including an explicit UTC offset."
    },
    "timezone": {
      "type": [
        "string",
        "null"
      ],
      "description": "IANA timezone used for appointment display and availability rules."
    }
  },
  "required": [
    "slot_start_at"
  ]
}
```

Example:

```json
{
  "slot_start_at": "2028-03-27T10:00:00+01:00",
  "timezone": "Europe/London"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "product_id": {
          "type": "integer"
        },
        "product_variant_id": {
          "type": "integer"
        },
        "order_id": {
          "type": "integer"
        },
        "invoice_id": {
          "type": "integer"
        },
        "customer_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "customer_email": {
          "type": [
            "string",
            "null"
          ],
          "format": "email"
        },
        "slot_start_at": {
          "type": "string",
          "format": "date-time"
        },
        "slot_end_at": {
          "type": "string",
          "format": "date-time"
        },
        "timezone": {
          "type": "string",
          "example": "Europe/London"
        },
        "quantity": {
          "type": "integer",
          "minimum": 1
        },
        "status": {
          "type": "string",
          "enum": [
            "pending",
            "confirmed",
            "cancelled",
            "needs_reschedule",
            "failed"
          ]
        },
        "calendar_sync_status": {
          "type": "string",
          "enum": [
            "pending",
            "synced",
            "skipped",
            "cancelled",
            "failed"
          ]
        },
        "external_event_link": {
          "type": [
            "string",
            "null"
          ],
          "format": "uri",
          "description": "Calendar event URL. Always null after cancellation."
        },
        "video_join_url": {
          "type": [
            "string",
            "null"
          ],
          "format": "uri",
          "description": "Video meeting URL. Always null after cancellation."
        },
        "confirmed_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "cancelled_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "product": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "id": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "title": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "variant": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "id": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "title": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "required": [
        "id",
        "product_id",
        "product_variant_id",
        "order_id",
        "invoice_id",
        "customer_id",
        "customer_email",
        "slot_start_at",
        "slot_end_at",
        "timezone",
        "quantity",
        "status",
        "calendar_sync_status",
        "external_event_link",
        "video_join_url",
        "confirmed_at",
        "cancelled_at",
        "created_at",
        "updated_at",
        "product",
        "variant"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": "018f61d6-1c46-7b42-8a94-522bc6b5c53f",
    "product_id": 41,
    "product_variant_id": 73,
    "order_id": 501,
    "invoice_id": 901,
    "customer_id": 301,
    "customer_email": "isabel.torres@example.com",
    "slot_start_at": "2028-03-27T09:00:00.000Z",
    "slot_end_at": "2028-03-27T09:30:00.000Z",
    "timezone": "Europe/London",
    "quantity": 1,
    "status": "confirmed",
    "calendar_sync_status": "synced",
    "external_event_link": "https://calendar.google.com/calendar/event?eid=example",
    "video_join_url": "https://meet.google.com/abc-defg-hij",
    "confirmed_at": "2028-03-01T12:00:00Z",
    "cancelled_at": null,
    "created_at": "2028-03-01T11:59:00Z",
    "updated_at": "2028-03-01T12:01:00.000000Z",
    "product": {
      "id": 41,
      "title": "Canva deck intervention"
    },
    "variant": {
      "id": 73,
      "title": "Thirty slides or thirty minutes"
    }
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v2/bookings/{booking}/status

Cancel an appointment

Cancel a store-owned appointment. Cancellation is the only supported administrative status transition. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.bookings.cancel({
  "booking": "018f61d6-1c46-7b42-8a94-522bc6b5c53f",
  "status": "cancelled"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.bookings.cancel(
    booking="018f61d6-1c46-7b42-8a94-522bc6b5c53f",
    status="cancelled"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->bookings()->cancel(
    booking: '018f61d6-1c46-7b42-8a94-522bc6b5c53f',
    status: 'cancelled',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.BookingsCancelParams{}
    if err := json.Unmarshal([]byte("{\"status\":\"cancelled\"}"), params); err != nil { panic(err) }
    result, err := client.Bookings().Cancel(context.Background(), "018f61d6-1c46-7b42-8a94-522bc6b5c53f", params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Bookings.CancelAsync(
    "018f61d6-1c46-7b42-8a94-522bc6b5c53f",
    new BookingsCancelOptions
    {
        Status = JsonConvert.DeserializeObject<string>("\"cancelled\"")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.bookings.cancel(booking = "018f61d6-1c46-7b42-8a94-522bc6b5c53f", status = "cancelled")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.bookings.cancel(
  booking: "018f61d6-1c46-7b42-8a94-522bc6b5c53f",
  status: "cancelled"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::bookings::CancelParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CancelParams::new(serde_json::from_str("{\"status\":\"cancelled\"}")?);
    let result = client.bookings().cancel("018f61d6-1c46-7b42-8a94-522bc6b5c53f", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Bookings.cancel(client, "018f61d6-1c46-7b42-8a94-522bc6b5c53f", %{"status" => "cancelled"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp bookings cancel 018f61d6-1c46-7b42-8a94-522bc6b5c53f --status cancelled --yes

```

- Method: `PATCH`

- Path: `/v2/bookings/{booking}/status`

- Full URL: `https://sell.app/api/v2/bookings/{booking}/status`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_BOOKING_ID='018f61d6-1c46-7b42-8a94-522bc6b5c53f'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/bookings/${SELLAPP_BOOKING_ID}/status" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "status": "cancelled"
}'
```

## Path Parameters
- `booking` (`string`, required): The appointment UUID or numeric ID.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "cancelled"
      ]
    }
  },
  "required": [
    "status"
  ]
}
```

Example:

```json
{
  "status": "cancelled"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "product_id": {
          "type": "integer"
        },
        "product_variant_id": {
          "type": "integer"
        },
        "order_id": {
          "type": "integer"
        },
        "invoice_id": {
          "type": "integer"
        },
        "customer_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "customer_email": {
          "type": [
            "string",
            "null"
          ],
          "format": "email"
        },
        "slot_start_at": {
          "type": "string",
          "format": "date-time"
        },
        "slot_end_at": {
          "type": "string",
          "format": "date-time"
        },
        "timezone": {
          "type": "string",
          "example": "Europe/London"
        },
        "quantity": {
          "type": "integer",
          "minimum": 1
        },
        "status": {
          "type": "string",
          "enum": [
            "pending",
            "confirmed",
            "cancelled",
            "needs_reschedule",
            "failed"
          ]
        },
        "calendar_sync_status": {
          "type": "string",
          "enum": [
            "pending",
            "synced",
            "skipped",
            "cancelled",
            "failed"
          ]
        },
        "external_event_link": {
          "type": [
            "string",
            "null"
          ],
          "format": "uri",
          "description": "Calendar event URL. Always null after cancellation."
        },
        "video_join_url": {
          "type": [
            "string",
            "null"
          ],
          "format": "uri",
          "description": "Video meeting URL. Always null after cancellation."
        },
        "confirmed_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "cancelled_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "product": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "id": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "title": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "variant": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "id": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "title": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "required": [
        "id",
        "product_id",
        "product_variant_id",
        "order_id",
        "invoice_id",
        "customer_id",
        "customer_email",
        "slot_start_at",
        "slot_end_at",
        "timezone",
        "quantity",
        "status",
        "calendar_sync_status",
        "external_event_link",
        "video_join_url",
        "confirmed_at",
        "cancelled_at",
        "created_at",
        "updated_at",
        "product",
        "variant"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": "018f61d6-1c46-7b42-8a94-522bc6b5c53f",
    "product_id": 41,
    "product_variant_id": 73,
    "order_id": 501,
    "invoice_id": 901,
    "customer_id": 301,
    "customer_email": "isabel.torres@example.com",
    "slot_start_at": "2028-03-26T09:00:00Z",
    "slot_end_at": "2028-03-26T09:30:00Z",
    "timezone": "Europe/London",
    "quantity": 1,
    "status": "cancelled",
    "calendar_sync_status": "cancelled",
    "external_event_link": null,
    "video_join_url": null,
    "confirmed_at": "2028-03-01T12:00:00Z",
    "cancelled_at": "2028-03-01T12:01:00.000000Z",
    "created_at": "2028-03-01T11:59:00Z",
    "updated_at": "2028-03-01T12:01:00.000000Z",
    "product": {
      "id": 41,
      "title": "Canva deck intervention"
    },
    "variant": {
      "id": 73,
      "title": "Thirty slides or thirty minutes"
    }
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Update booking configuration (/docs/api/bookings/update-booking-configuration)

Duration, buffers, and weekly time boundaries use 30-minute increments. Provider connection IDs must belong to the selected store. Google Meet requires a same-store Google Calendar connection.

## PATCH /v2/products/{product}/variants/{variant}/booking

Update booking configuration

Partially update a booking variant's configuration. Provider connection IDs must belong to the selected store; secret credentials are never accepted or returned here. Requires the `listing` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.productVariantsBooking.update({
  "product": "41",
  "variant": 73,
  "timezone": "Europe/London",
  "durationMinutes": 60,
  "capacityPerSlot": 1,
  "minNoticeMinutes": 1440,
  "maxAdvanceDays": 60
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.product_variants_booking.update(
    product="41",
    variant=73,
    timezone="Europe/London",
    duration_minutes=60,
    capacity_per_slot=1,
    min_notice_minutes=1440,
    max_advance_days=60
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->productVariantsBooking()->update(
    product: '41',
    variant: 73,
    timezone: 'Europe/London',
    durationMinutes: 60,
    capacityPerSlot: 1,
    minNoticeMinutes: 1440,
    maxAdvanceDays: 60,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.ProductVariantsBookingUpdateParams{}
    if err := json.Unmarshal([]byte("{\"timezone\":\"Europe/London\",\"duration_minutes\":60,\"capacity_per_slot\":1,\"min_notice_minutes\":1440,\"max_advance_days\":60}"), params); err != nil { panic(err) }
    result, err := client.ProductVariantsBooking().Update(context.Background(), "41", 73, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.ProductVariantsBooking.UpdateAsync(
    "41",
    "73",
    new ProductVariantsBookingUpdateOptions
    {
        Timezone = "Europe/London",
        DurationMinutes = 60,
        CapacityPerSlot = 1,
        MinNoticeMinutes = 1440,
        MaxAdvanceDays = 60,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.productVariantsBooking.update(product = "41", variant = "73", timezone = app.sell.sellapp.common.http.PatchField.Present("Europe/London"), durationMinutes = app.sell.sellapp.common.http.PatchField.Present(60L), capacityPerSlot = app.sell.sellapp.common.http.PatchField.Present(1L), minNoticeMinutes = app.sell.sellapp.common.http.PatchField.Present(1440L), maxAdvanceDays = app.sell.sellapp.common.http.PatchField.Present(60L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.product_variants_booking.update(
  product: "41",
  variant: 73,
  timezone: "Europe/London",
  duration_minutes: 60,
  capacity_per_slot: 1,
  min_notice_minutes: 1440,
  max_advance_days: 60
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::product_variants_booking::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{\"timezone\":\"Europe/London\",\"duration_minutes\":60,\"capacity_per_slot\":1,\"min_notice_minutes\":1440,\"max_advance_days\":60}")?);
    let result = client.product_variants_booking().update("41", "73", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.ProductVariantsBooking.update(client, "41", 73, %{"timezone" => "Europe/London", "duration_minutes" => 60, "capacity_per_slot" => 1, "min_notice_minutes" => 1440, "max_advance_days" => 60})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp product-variants booking update --product 41 73 --timezone Europe/London --duration-minutes 60 --capacity-per-slot 1 --min-notice-minutes 1440 --max-advance-days 60 --yes

```

- Method: `PATCH`

- Path: `/v2/products/{product}/variants/{variant}/booking`

- Full URL: `https://sell.app/api/v2/products/{product}/variants/{variant}/booking`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_ID='41'
export SELLAPP_VARIANT_ID='73'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/products/${SELLAPP_PRODUCT_ID}/variants/${SELLAPP_VARIANT_ID}/booking" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "timezone": "Europe/London",
  "duration_minutes": 60,
  "capacity_per_slot": 1,
  "min_notice_minutes": 1440,
  "max_advance_days": 60
}'
```

## Path Parameters
- `product` (`string`, required): The booking product ID or slug.
- `variant` (`integer`, required): The variant path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "mode": {
      "type": "string",
      "enum": [
        "native"
      ]
    },
    "conflict_scope": {
      "type": "string",
      "enum": [
        "product",
        "variant"
      ]
    },
    "timezone": {
      "type": "string",
      "example": "America/New_York"
    },
    "duration_minutes": {
      "type": "integer",
      "minimum": 30,
      "multipleOf": 30
    },
    "capacity_per_slot": {
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "min_notice_minutes": {
      "type": "integer",
      "minimum": 0,
      "maximum": 525600
    },
    "max_advance_days": {
      "type": "integer",
      "minimum": 1,
      "maximum": 730
    },
    "buffer_before_minutes": {
      "type": "integer",
      "minimum": 0,
      "maximum": 1440,
      "multipleOf": 30
    },
    "buffer_after_minutes": {
      "type": "integer",
      "minimum": 0,
      "maximum": 1440,
      "multipleOf": 30
    },
    "availability": {
      "type": "array",
      "minItems": 7,
      "maxItems": 7,
      "items": {
        "type": "object",
        "properties": {
          "day": {
            "type": "integer",
            "minimum": 1,
            "maximum": 7
          },
          "enabled": {
            "type": "boolean"
          },
          "start": {
            "type": "string",
            "example": "09:00"
          },
          "end": {
            "type": "string",
            "example": "17:00"
          }
        },
        "required": [
          "day",
          "enabled",
          "start",
          "end"
        ]
      }
    },
    "provider_connection_ids": {
      "type": "array",
      "items": {
        "type": "integer"
      }
    },
    "video_provider": {
      "type": "string",
      "enum": [
        "none",
        "google_meet",
        "zoom"
      ]
    },
    "video_provider_connection_id": {
      "type": [
        "integer",
        "null"
      ]
    },
    "reminders_enabled": {
      "type": "boolean"
    },
    "reminder_offset_value": {
      "type": "integer",
      "minimum": 1,
      "maximum": 10080
    },
    "reminder_offset_unit": {
      "type": "string",
      "enum": [
        "minutes",
        "hours",
        "days",
        "weeks"
      ]
    },
    "meta": {
      "anyOf": [
        {
          "type": "object",
          "additionalProperties": true
        },
        {
          "type": "null"
        }
      ]
    }
  }
}
```

Example:

```json
{
  "timezone": "Europe/London",
  "duration_minutes": 60,
  "capacity_per_slot": 1,
  "min_notice_minutes": 1440,
  "max_advance_days": 60
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "product_id": {
          "type": "integer",
          "readOnly": true
        },
        "product_variant_id": {
          "type": "integer",
          "readOnly": true
        },
        "mode": {
          "type": "string",
          "enum": [
            "native"
          ]
        },
        "conflict_scope": {
          "type": "string",
          "enum": [
            "product",
            "variant"
          ]
        },
        "timezone": {
          "type": "string",
          "example": "America/New_York"
        },
        "duration_minutes": {
          "type": "integer",
          "minimum": 30,
          "multipleOf": 30
        },
        "capacity_per_slot": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000
        },
        "min_notice_minutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 525600
        },
        "max_advance_days": {
          "type": "integer",
          "minimum": 1,
          "maximum": 730
        },
        "buffer_before_minutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1440,
          "multipleOf": 30
        },
        "buffer_after_minutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1440,
          "multipleOf": 30
        },
        "availability": {
          "type": "array",
          "minItems": 7,
          "maxItems": 7,
          "items": {
            "type": "object",
            "properties": {
              "day": {
                "type": "integer",
                "minimum": 1,
                "maximum": 7
              },
              "enabled": {
                "type": "boolean"
              },
              "start": {
                "type": "string",
                "example": "09:00"
              },
              "end": {
                "type": "string",
                "example": "17:00"
              }
            },
            "required": [
              "day",
              "enabled",
              "start",
              "end"
            ]
          }
        },
        "provider_connection_ids": {
          "type": "array",
          "items": {
            "type": "integer"
          }
        },
        "video_provider": {
          "type": "string",
          "enum": [
            "none",
            "google_meet",
            "zoom"
          ]
        },
        "video_provider_connection_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "reminders_enabled": {
          "type": "boolean"
        },
        "reminder_offset_value": {
          "type": "integer",
          "minimum": 1,
          "maximum": 10080
        },
        "reminder_offset_unit": {
          "type": "string",
          "enum": [
            "minutes",
            "hours",
            "days",
            "weeks"
          ]
        },
        "meta": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": true
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "required": [
        "product_id",
        "product_variant_id",
        "mode",
        "conflict_scope",
        "timezone",
        "duration_minutes",
        "capacity_per_slot",
        "min_notice_minutes",
        "max_advance_days",
        "buffer_before_minutes",
        "buffer_after_minutes",
        "availability",
        "provider_connection_ids",
        "video_provider",
        "video_provider_connection_id",
        "reminders_enabled",
        "reminder_offset_value",
        "reminder_offset_unit",
        "meta"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "product_id": 41,
    "product_variant_id": 73,
    "mode": "native",
    "conflict_scope": "variant",
    "timezone": "Europe/London",
    "duration_minutes": 60,
    "capacity_per_slot": 1,
    "min_notice_minutes": 1440,
    "max_advance_days": 60,
    "buffer_before_minutes": 0,
    "buffer_after_minutes": 0,
    "availability": [
      {
        "day": 1,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 2,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 3,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 4,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 5,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 6,
        "enabled": false,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 7,
        "enabled": false,
        "start": "09:00",
        "end": "17:00"
      }
    ],
    "provider_connection_ids": [],
    "video_provider": "none",
    "video_provider_connection_id": null,
    "reminders_enabled": false,
    "reminder_offset_value": 1,
    "reminder_offset_unit": "hours",
    "meta": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PUT /v2/products/{product}/variants/{variant}/booking

Update booking configuration

Partially update a booking variant's configuration. Provider connection IDs must belong to the selected store; secret credentials are never accepted or returned here. Requires the `listing` Sanctum ability. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.productVariantsBooking.replace({
  "product": "41",
  "variant": 73,
  "timezone": "Europe/London",
  "durationMinutes": 60,
  "capacityPerSlot": 1,
  "minNoticeMinutes": 1440,
  "maxAdvanceDays": 60
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.product_variants_booking.replace(
    product="41",
    variant=73,
    timezone="Europe/London",
    duration_minutes=60,
    capacity_per_slot=1,
    min_notice_minutes=1440,
    max_advance_days=60
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->productVariantsBooking()->replace(
    product: '41',
    variant: 73,
    timezone: 'Europe/London',
    durationMinutes: 60,
    capacityPerSlot: 1,
    minNoticeMinutes: 1440,
    maxAdvanceDays: 60,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.ProductVariantsBookingReplaceParams{}
    if err := json.Unmarshal([]byte("{\"timezone\":\"Europe/London\",\"duration_minutes\":60,\"capacity_per_slot\":1,\"min_notice_minutes\":1440,\"max_advance_days\":60}"), params); err != nil { panic(err) }
    result, err := client.ProductVariantsBooking().Replace(context.Background(), "41", 73, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.ProductVariantsBooking.ReplaceAsync(
    "41",
    "73",
    new ProductVariantsBookingReplaceOptions
    {
        Timezone = "Europe/London",
        DurationMinutes = 60,
        CapacityPerSlot = 1,
        MinNoticeMinutes = 1440,
        MaxAdvanceDays = 60,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.productVariantsBooking.replace(product = "41", variant = "73", timezone = "Europe/London", durationMinutes = 60L, capacityPerSlot = 1L, minNoticeMinutes = 1440L, maxAdvanceDays = 60L)
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.product_variants_booking.replace(
  product: "41",
  variant: 73,
  timezone: "Europe/London",
  duration_minutes: 60,
  capacity_per_slot: 1,
  min_notice_minutes: 1440,
  max_advance_days: 60
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::product_variants_booking::ReplaceParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceParams::new(serde_json::from_str("{\"timezone\":\"Europe/London\",\"duration_minutes\":60,\"capacity_per_slot\":1,\"min_notice_minutes\":1440,\"max_advance_days\":60}")?);
    let result = client.product_variants_booking().replace("41", "73", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.ProductVariantsBooking.replace(client, "41", 73, %{"timezone" => "Europe/London", "duration_minutes" => 60, "capacity_per_slot" => 1, "min_notice_minutes" => 1440, "max_advance_days" => 60})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp product-variants booking replace --product 41 73 --timezone Europe/London --duration-minutes 60 --capacity-per-slot 1 --min-notice-minutes 1440 --max-advance-days 60 --yes

```

- Method: `PUT`

- Path: `/v2/products/{product}/variants/{variant}/booking`

- Full URL: `https://sell.app/api/v2/products/{product}/variants/{variant}/booking`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_ID='41'
export SELLAPP_VARIANT_ID='73'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/products/${SELLAPP_PRODUCT_ID}/variants/${SELLAPP_VARIANT_ID}/booking" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "timezone": "Europe/London",
  "duration_minutes": 60,
  "capacity_per_slot": 1,
  "min_notice_minutes": 1440,
  "max_advance_days": 60
}'
```

## Path Parameters
- `product` (`string`, required): The booking product ID or slug.
- `variant` (`integer`, required): The variant path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "mode": {
      "type": "string",
      "enum": [
        "native"
      ]
    },
    "conflict_scope": {
      "type": "string",
      "enum": [
        "product",
        "variant"
      ]
    },
    "timezone": {
      "type": "string",
      "example": "America/New_York"
    },
    "duration_minutes": {
      "type": "integer",
      "minimum": 30,
      "multipleOf": 30
    },
    "capacity_per_slot": {
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "min_notice_minutes": {
      "type": "integer",
      "minimum": 0,
      "maximum": 525600
    },
    "max_advance_days": {
      "type": "integer",
      "minimum": 1,
      "maximum": 730
    },
    "buffer_before_minutes": {
      "type": "integer",
      "minimum": 0,
      "maximum": 1440,
      "multipleOf": 30
    },
    "buffer_after_minutes": {
      "type": "integer",
      "minimum": 0,
      "maximum": 1440,
      "multipleOf": 30
    },
    "availability": {
      "type": "array",
      "minItems": 7,
      "maxItems": 7,
      "items": {
        "type": "object",
        "properties": {
          "day": {
            "type": "integer",
            "minimum": 1,
            "maximum": 7
          },
          "enabled": {
            "type": "boolean"
          },
          "start": {
            "type": "string",
            "example": "09:00"
          },
          "end": {
            "type": "string",
            "example": "17:00"
          }
        },
        "required": [
          "day",
          "enabled",
          "start",
          "end"
        ]
      }
    },
    "provider_connection_ids": {
      "type": "array",
      "items": {
        "type": "integer"
      }
    },
    "video_provider": {
      "type": "string",
      "enum": [
        "none",
        "google_meet",
        "zoom"
      ]
    },
    "video_provider_connection_id": {
      "type": [
        "integer",
        "null"
      ]
    },
    "reminders_enabled": {
      "type": "boolean"
    },
    "reminder_offset_value": {
      "type": "integer",
      "minimum": 1,
      "maximum": 10080
    },
    "reminder_offset_unit": {
      "type": "string",
      "enum": [
        "minutes",
        "hours",
        "days",
        "weeks"
      ]
    },
    "meta": {
      "anyOf": [
        {
          "type": "object",
          "additionalProperties": true
        },
        {
          "type": "null"
        }
      ]
    }
  }
}
```

Example:

```json
{
  "timezone": "Europe/London",
  "duration_minutes": 60,
  "capacity_per_slot": 1,
  "min_notice_minutes": 1440,
  "max_advance_days": 60
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "product_id": {
          "type": "integer",
          "readOnly": true
        },
        "product_variant_id": {
          "type": "integer",
          "readOnly": true
        },
        "mode": {
          "type": "string",
          "enum": [
            "native"
          ]
        },
        "conflict_scope": {
          "type": "string",
          "enum": [
            "product",
            "variant"
          ]
        },
        "timezone": {
          "type": "string",
          "example": "America/New_York"
        },
        "duration_minutes": {
          "type": "integer",
          "minimum": 30,
          "multipleOf": 30
        },
        "capacity_per_slot": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000
        },
        "min_notice_minutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 525600
        },
        "max_advance_days": {
          "type": "integer",
          "minimum": 1,
          "maximum": 730
        },
        "buffer_before_minutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1440,
          "multipleOf": 30
        },
        "buffer_after_minutes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1440,
          "multipleOf": 30
        },
        "availability": {
          "type": "array",
          "minItems": 7,
          "maxItems": 7,
          "items": {
            "type": "object",
            "properties": {
              "day": {
                "type": "integer",
                "minimum": 1,
                "maximum": 7
              },
              "enabled": {
                "type": "boolean"
              },
              "start": {
                "type": "string",
                "example": "09:00"
              },
              "end": {
                "type": "string",
                "example": "17:00"
              }
            },
            "required": [
              "day",
              "enabled",
              "start",
              "end"
            ]
          }
        },
        "provider_connection_ids": {
          "type": "array",
          "items": {
            "type": "integer"
          }
        },
        "video_provider": {
          "type": "string",
          "enum": [
            "none",
            "google_meet",
            "zoom"
          ]
        },
        "video_provider_connection_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "reminders_enabled": {
          "type": "boolean"
        },
        "reminder_offset_value": {
          "type": "integer",
          "minimum": 1,
          "maximum": 10080
        },
        "reminder_offset_unit": {
          "type": "string",
          "enum": [
            "minutes",
            "hours",
            "days",
            "weeks"
          ]
        },
        "meta": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": true
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "required": [
        "product_id",
        "product_variant_id",
        "mode",
        "conflict_scope",
        "timezone",
        "duration_minutes",
        "capacity_per_slot",
        "min_notice_minutes",
        "max_advance_days",
        "buffer_before_minutes",
        "buffer_after_minutes",
        "availability",
        "provider_connection_ids",
        "video_provider",
        "video_provider_connection_id",
        "reminders_enabled",
        "reminder_offset_value",
        "reminder_offset_unit",
        "meta"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "product_id": 41,
    "product_variant_id": 73,
    "mode": "native",
    "conflict_scope": "variant",
    "timezone": "Europe/London",
    "duration_minutes": 60,
    "capacity_per_slot": 1,
    "min_notice_minutes": 1440,
    "max_advance_days": 60,
    "buffer_before_minutes": 0,
    "buffer_after_minutes": 0,
    "availability": [
      {
        "day": 1,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 2,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 3,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 4,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 5,
        "enabled": true,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 6,
        "enabled": false,
        "start": "09:00",
        "end": "17:00"
      },
      {
        "day": 7,
        "enabled": false,
        "start": "09:00",
        "end": "17:00"
      }
    ],
    "provider_connection_ids": [],
    "video_provider": "none",
    "video_provider_connection_id": null,
    "reminders_enabled": false,
    "reminder_offset_value": 1,
    "reminder_offset_unit": "hours",
    "meta": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Create a charge (/docs/api/charges/create-a-charge)

Create a standalone charge for a payment or a free claim.

Pass `locale` or `language` to control the hosted checkout language. For example, `pt-BR` is stored as `pt_BR` on the created charge.

## POST /v2/charges

Create a charge

Create a standalone charge for payment or a free claim. Requires the charge API ability and store permission. The total is an integer in the currency's minor units: 1999 USD means $19.99. Supplying currency requires total. For a positive paid charge, choose enabled payment_method/payment_methods or use_all_payment_methods; availability depends on the store and currency, and custom payment methods are unsupported for paid charges. Creating a charge does not prove payment. A repeated create may create another charge; check the original result before retrying. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.charges.create({
  "email": "sofia.rivera@example.com",
  "returnUrl": "https://example.com/launch-complete",
  "reference": "One more thing launch",
  "currency": "USD",
  "total": 10000,
  "paymentMethod": "PAYPAL"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.charges.create(
    email="sofia.rivera@example.com",
    return_url="https://example.com/launch-complete",
    reference="One more thing launch",
    currency="USD",
    total=10000,
    payment_method="PAYPAL"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->charges()->create(
    email: 'sofia.rivera@example.com',
    returnUrl: 'https://example.com/launch-complete',
    reference: 'One more thing launch',
    currency: 'USD',
    total: 10000,
    paymentMethod: 'PAYPAL',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.ChargesCreateParams{}
    if err := json.Unmarshal([]byte("{\"email\":\"sofia.rivera@example.com\",\"return_url\":\"https://example.com/launch-complete\",\"reference\":\"One more thing launch\",\"currency\":\"USD\",\"total\":10000,\"payment_method\":\"PAYPAL\"}"), params); err != nil { panic(err) }
    result, err := client.Charges().Create(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Charges.CreateAsync(new ChargesCreateOptions
    {
        Email = "sofia.rivera@example.com",
        ReturnUrl = "https://example.com/launch-complete",
        Reference = JsonConvert.DeserializeObject<string?>("\"One more thing launch\"")!,
        Currency = "USD",
        Total = 10000,
        PaymentMethod = JsonConvert.DeserializeObject<SdkCreateChargeRequestApplicationJsonPaymentMethod>("\"PAYPAL\"")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.charges.create(email = "sofia.rivera@example.com", returnUrl = "https://example.com/launch-complete", reference = "One more thing launch", currency = "USD", total = 10000L, paymentMethod = app.sell.sellapp.types.PaymentMethod("PAYPAL"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.charges.create(
  email: "sofia.rivera@example.com",
  return_url: "https://example.com/launch-complete",
  reference: "One more thing launch",
  currency: "USD",
  total: 10000,
  payment_method: "PAYPAL"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::charges::CreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateParams::new(serde_json::from_str("{\"email\":\"sofia.rivera@example.com\",\"return_url\":\"https://example.com/launch-complete\",\"currency\":\"USD\",\"total\":10000,\"payment_method\":\"PAYPAL\",\"reference\":\"One more thing launch\"}")?);
    let result = client.charges().create(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Charges.create(client, %{"email" => "sofia.rivera@example.com", "return_url" => "https://example.com/launch-complete", "reference" => "One more thing launch", "currency" => "USD", "total" => 10000, "payment_method" => "PAYPAL"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp charges create --email 'sofia.rivera@example.com' --return-url https://example.com/launch-complete --currency USD --total 10000 --payment-method PAYPAL --reference 'One more thing launch' --yes

```

- Method: `POST`

- Path: `/v2/charges`

- Full URL: `https://sell.app/api/v2/charges`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/charges" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "email": "sofia.rivera@example.com",
  "return_url": "https://example.com/launch-complete",
  "currency": "USD",
  "total": 10000,
  "payment_method": "PAYPAL",
  "reference": "One more thing launch"
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "format": "email"
    },
    "return_url": {
      "type": "string",
      "format": "uri"
    },
    "cancel_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "webhook": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri",
      "description": "Optional public webhook destination validated for safe delivery. A browser return is not payment confirmation."
    },
    "reference": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 255
    },
    "description": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 255
    },
    "currency": {
      "type": "string",
      "minLength": 3,
      "maxLength": 3,
      "description": "Supported three-letter currency code, normalized to uppercase. Defaults to USD when omitted. When supplied, total is required; supply both for a paid charge."
    },
    "total": {
      "type": "integer",
      "minimum": 0,
      "description": "Integer minor units in currency; 1999 USD is $19.99. Required when currency is supplied. Maximum is the minor-unit equivalent of 99,999,999 major currency units. Omit total and currency together for a free USD claim."
    },
    "payment_method": {
      "type": "string",
      "enum": [
        "AUTHNET",
        "BTCPAY",
        "CASHAPP",
        "COINBASE",
        "PADDLE",
        "PAYDASH",
        "PAYPAL",
        "PAYSTACK",
        "SQUARE",
        "STRIPE",
        "VENMO",
        "NMI",
        "MERCADO_PAGO",
        "MOLLIE",
        "RAZORPAY",
        "CUSTOM_PAYMENT_METHOD",
        "LIFI",
        "BTC",
        "LTC",
        "ETH",
        "XMR",
        "SOL",
        "ADA",
        "BNB",
        "TRX",
        "MATIC",
        "ETH_USDT",
        "ETH_USDC",
        "ETH_UNI",
        "ETH_SHIB",
        "ETH_DAI",
        "BNB_USDT",
        "BNB_USDC",
        "TRX_USDT",
        "TRX_USDC",
        "SOL_USDT",
        "SOL_USDC"
      ]
    },
    "payment_methods": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "AUTHNET",
          "BTCPAY",
          "CASHAPP",
          "COINBASE",
          "PADDLE",
          "PAYDASH",
          "PAYPAL",
          "PAYSTACK",
          "SQUARE",
          "STRIPE",
          "VENMO",
          "NMI",
          "MERCADO_PAGO",
          "MOLLIE",
          "RAZORPAY",
          "CUSTOM_PAYMENT_METHOD",
          "LIFI",
          "BTC",
          "LTC",
          "ETH",
          "XMR",
          "SOL",
          "ADA",
          "BNB",
          "TRX",
          "MATIC",
          "ETH_USDT",
          "ETH_USDC",
          "ETH_UNI",
          "ETH_SHIB",
          "ETH_DAI",
          "BNB_USDT",
          "BNB_USDC",
          "TRX_USDT",
          "TRX_USDC",
          "SOL_USDT",
          "SOL_USDC"
        ]
      },
      "minItems": 1
    },
    "use_all_payment_methods": {
      "type": "boolean"
    },
    "deliverable": {
      "anyOf": [
        {
          "type": "object",
          "additionalProperties": true
        },
        {
          "type": "null"
        }
      ]
    },
    "metadata": {
      "anyOf": [
        {
          "type": "object",
          "description": "Custom charge metadata. The `wallet` key is reserved by SellApp and cannot be provided.",
          "additionalProperties": true
        },
        {
          "type": "null"
        }
      ],
      "description": "Optional metadata. The wallet key is prohibited; standalone charge creation cannot create a wallet top-up."
    },
    "coupon_code": {
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "email",
    "return_url"
  ]
}
```

Example:

```json
{
  "email": "sofia.rivera@example.com",
  "return_url": "https://example.com/launch-complete",
  "currency": "USD",
  "total": 10000,
  "payment_method": "PAYPAL",
  "reference": "One more thing launch"
}
```

## Responses

### 201

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "url": {
          "type": "string"
        },
        "status": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "url",
        "status"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "url": "https://sell.app/store/charges/select/1?signature=...",
    "status": "PENDING"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Overview (/docs/api/charges)



A charge collects a standalone payment without managing product variants or
delivery. Use one when your own app handles what the customer receives.

Create a charge, send the returned checkout URL to the customer, and confirm
the result through the charge API or a signed webhook. Marking a charge
completed or voided changes the payment record; check its current state before
trying again after a lost response. The `charge` ability and permissions for the selected store are required.

The operation schemas define money fields, gateway metadata, status values, and
nullable properties.

## Endpoints [#endpoints]

* [List charges](/api/charges/list-all-charges)
* [Create a charge](/api/charges/create-a-charge)
* [Retrieve a charge](/api/charges/retrieve-a-charge)
* [Mark completed](/api/charges/mark-pending-charge-completed)
* [Mark voided](/api/charges/mark-pending-charge-voided)


# List all charges (/docs/api/charges/list-all-charges)

Retrieves a paginated list of charges for your store.

## GET /v2/charges

List all charges

Retrieve a paginated list of charges for your store. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.charges.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.charges.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->charges()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.ChargesListParams{}
    page := client.Charges().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Charges.ListAsync(new ChargesListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.charges.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.charges.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::charges::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.charges().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Charges.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp charges list

```

- Method: `GET`

- Path: `/v2/charges`

- Full URL: `https://sell.app/api/v2/charges`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/charges" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "url": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "status"
        ]
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "url": "https://sell.app/store/charges/select/1?signature=...",
      "status": "PENDING"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/charges?page=1",
    "last": "https://sell.app/api/v2/charges?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/charges",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/charges?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Mark pending charge completed (/docs/api/charges/mark-pending-charge-completed)

Manually marks a pending charge as completed.

<Warn>
  This action should only be performed on charges with a `PENDING` status and where you're certain you've received the funds. Attempting to mark a charge with a different status as completed will result in an error.
</Warn>

## PUT /v2/charges/{charge_id}/completed

Mark pending charge completed

Manually mark a PENDING or VOIDED charge completed after independently verifying receipt of funds. This does not collect, capture, or verify payment. Wallet top-up charges cannot be completed manually. Completion emits charge.completed webhooks and store notifications and records applicable platform fees. Requires the charge API ability and update permission. A charge already completed returns 422; retrieve its state before retrying. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.charges.markCompleted({
  "chargeId": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.charges.mark_completed(charge_id=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->charges()->markCompleted(chargeId: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Charges().MarkCompleted(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Charges.MarkCompletedAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.charges.markCompleted(chargeId = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.charges.mark_completed(charge_id: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::charges::MarkCompletedParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = MarkCompletedParams::default();
    let result = client.charges().mark_completed("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Charges.mark_completed(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp charges mark-completed 1 --yes

```

- Method: `PUT`

- Path: `/v2/charges/{charge_id}/completed`

- Full URL: `https://sell.app/api/v2/charges/{charge_id}/completed`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CHARGE_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/charges/${SELLAPP_CHARGE_ID}/completed" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `charge_id` (`integer`, required): The charge id path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "message": {
      "type": "string"
    }
  },
  "required": [
    "message"
  ]
}
```

Example:

```json
{
  "message": "Charge Completed Successfully"
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Mark pending charge voided (/docs/api/charges/mark-pending-charge-voided)

Manually marks a pending charge as voided (canceled).

<Warn>
  This action should only be performed on charges with a `PENDING` status. Attempting to void a charge with a different status will result in an error.
</Warn>

## PUT /v2/charges/{charge_id}/voided

Mark pending charge voided

Void a PENDING charge. This cancels the internal charge, releases an applicable redeemed reward coupon, and emits charge.voided; it does not refund a payment. Requires the charge API ability and update permission. Other states return 422, including a repeat after successful voiding; retrieve its state before retrying. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.charges.markVoided({
  "chargeId": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.charges.mark_voided(charge_id=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->charges()->markVoided(chargeId: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Charges().MarkVoided(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Charges.MarkVoidedAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.charges.markVoided(chargeId = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.charges.mark_voided(charge_id: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::charges::MarkVoidedParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = MarkVoidedParams::default();
    let result = client.charges().mark_voided("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Charges.mark_voided(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp charges mark-voided 1 --yes

```

- Method: `PUT`

- Path: `/v2/charges/{charge_id}/voided`

- Full URL: `https://sell.app/api/v2/charges/{charge_id}/voided`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CHARGE_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/charges/${SELLAPP_CHARGE_ID}/voided" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `charge_id` (`integer`, required): The charge id path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "message": {
      "type": "string"
    }
  },
  "required": [
    "message"
  ]
}
```

Example:

```json
{
  "message": "Charge Voided Successfully"
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve a charge (/docs/api/charges/retrieve-a-charge)

Retrieve a charge by its ID to check its details and payment state.

## GET /v2/charges/{charge}

Retrieve a charge

Retrieve a charge by its ID to check its details and payment state. The response schema describes the returned fields. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.charges.get({
  "charge": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.charges.get(charge=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->charges()->get(charge: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Charges().Get(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Charges.GetAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.charges.get(charge = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.charges.get(charge: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::charges::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.charges().get("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Charges.get(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp charges get 1

```

- Method: `GET`

- Path: `/v2/charges/{charge}`

- Full URL: `https://sell.app/api/v2/charges/{charge}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CHARGE_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/charges/${SELLAPP_CHARGE_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `charge` (`integer`, required): The charge path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "url": {
          "type": "string"
        },
        "status": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "url",
        "status"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "url": "https://sell.app/store/charges/select/1?signature=...",
    "status": "PENDING"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Batch create coupons (/docs/api/coupons/batch-create-coupons)

Create multiple coupons in one request by sending a `resources` array.

Each resource supports the same product and variant scoping as the single-create endpoint. Set `store_wide` to `false`, provide `products`, and optionally provide `product_variants`. Each variant must belong to one of the selected products.

```json
{
  "resources": [
    {
      "code": "STARTER10",
      "type": "PERCENTAGE",
      "discount": 10,
      "store_wide": false,
      "products": [123],
      "product_variants": [1001]
    }
  ]
}
```

## POST /v2/coupons/batch

Batch create coupons

Create multiple coupons in one request by sending a `resources` array. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.v2BatchCreateCoupons({
  "resources": [{"code": "STARTER10", "type": "PERCENTAGE", "discount": 10, "storeWide": false, "products": [123], "productVariants": [1001]}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.v2_batch_create_coupons(
    resources=[
        {
            "code": "STARTER10",
            "type": "PERCENTAGE",
            "discount": 10,
            "store_wide": False,
            "products": [123],
            "product_variants": [1001]
        }
    ]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->v2BatchCreateCoupons(
    resources: [
        [
            'code' => 'STARTER10',
            'type' => 'PERCENTAGE',
            'discount' => 10,
            'store_wide' => false,
            'products' => [123],
            'product_variants' => [1001],
        ],
    ],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsV2BatchCreateCouponsParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[{\"code\":\"STARTER10\",\"type\":\"PERCENTAGE\",\"discount\":10,\"store_wide\":false,\"products\":[123],\"product_variants\":[1001]}]}"), params); err != nil { panic(err) }
    result, err := client.Coupons().V2BatchCreateCoupons(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.V2BatchCreateCouponsAsync(new CouponsV2BatchCreateCouponsOptions
    {
        Resources = JsonConvert.DeserializeObject<List<V2BatchCreateCouponsRequestApplicationJsonPropertyResourcesItem>>("[{\"code\":\"STARTER10\",\"type\":\"PERCENTAGE\",\"discount\":10,\"store_wide\":false,\"products\":[123],\"product_variants\":[1001]}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.v2BatchCreateCoupons(resources = listOf(ObjectMapperFactory.read("{\"code\":\"STARTER10\",\"type\":\"PERCENTAGE\",\"discount\":10,\"store_wide\":false,\"products\":[123],\"product_variants\":[1001]}", app.sell.sellapp.models.V2BatchCreateCouponsRequestApplicationJsonPropertyResourcesItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.v2_batch_create_coupons(
  resources: [
    {
      code: "STARTER10",
      type: "PERCENTAGE",
      discount: 10,
      store_wide: false,
      products: [123],
      product_variants: [1001]
    }
  ]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::V2BatchCreateCouponsParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2BatchCreateCouponsParams::new(serde_json::from_str("{\"resources\":[{\"code\":\"STARTER10\",\"type\":\"PERCENTAGE\",\"discount\":10,\"store_wide\":false,\"products\":[123],\"product_variants\":[1001]}]}")?);
    let result = client.coupons().v_2_batch_create_coupons(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.v2_batch_create_coupons(client, %{"resources" => [%{"code" => "STARTER10", "type" => "PERCENTAGE", "discount" => 10, "store_wide" => false, "products" => [123], "product_variants" => [1001]}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons v-2-batch-create-coupons --body '{"resources":[{"code":"STARTER10","type":"PERCENTAGE","discount":10,"store_wide":false,"products":[123],"product_variants":[1001]}]}' --yes

```

- Method: `POST`

- Path: `/v2/coupons/batch`

- Full URL: `https://sell.app/api/v2/coupons/batch`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/coupons/batch" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    {
      "code": "STARTER10",
      "type": "PERCENTAGE",
      "discount": 10,
      "store_wide": false,
      "products": [
        123
      ],
      "product_variants": [
        1001
      ]
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, optional): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 255
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": [
              "number",
              "string"
            ],
            "minimum": 1,
            "maxLength": 255,
            "description": "A decimal discount value of at least 1. Percentage discounts cannot exceed 100; amount discounts use the store currency's major unit."
          },
          "store_wide": {
            "type": "boolean"
          },
          "products": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "integer"
            },
            "description": "Product IDs the coupon applies to when store_wide is false."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Optional variant restrictions. Every variant must belong to a selected product. Products without listed variants remain eligible on all variants."
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "A future date and time, or null for no expiry."
          },
          "minimum_amount": {
            "type": [
              "number",
              "string",
              "null"
            ],
            "minimum": 1,
            "maxLength": 255,
            "description": "A decimal minimum order amount in the store currency's major unit, or null for no minimum."
          }
        },
        "required": [
          "code",
          "type",
          "discount",
          "store_wide"
        ]
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    {
      "code": "STARTER10",
      "type": "PERCENTAGE",
      "discount": 10,
      "store_wide": false,
      "products": [
        123
      ],
      "product_variants": [
        1001
      ]
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": "string"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "store_wide": {
            "type": "boolean"
          },
          "minimum_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
            "example": "2026-07-03 12:15:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "maximum_discount_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
          },
          "products": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "discount",
          "limit",
          "store_wide",
          "minimum_amount",
          "expires_at",
          "created_at",
          "updated_at",
          "store_id",
          "deleted_at",
          "maximum_discount_amount",
          "products",
          "product_variants"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "code": "STARTER10",
      "type": "PERCENTAGE",
      "discount": "10",
      "limit": null,
      "store_wide": false,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2026-08-30T12:00:01.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "deleted_at": null,
      "products": [
        123
      ],
      "product_variants": [
        1001
      ],
      "maximum_discount_amount": null
    }
  ]
}
```

### 201

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": "string"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "store_wide": {
            "type": "boolean"
          },
          "minimum_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
            "example": "2026-07-03 12:15:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "maximum_discount_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
          },
          "products": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "discount",
          "limit",
          "store_wide",
          "minimum_amount",
          "expires_at",
          "created_at",
          "updated_at",
          "store_id",
          "deleted_at",
          "maximum_discount_amount",
          "products",
          "product_variants"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "code": "STARTER10",
      "type": "PERCENTAGE",
      "discount": "10",
      "limit": null,
      "store_wide": false,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2026-08-30T12:00:01.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "deleted_at": null,
      "products": [
        123
      ],
      "product_variants": [
        1001
      ],
      "maximum_discount_amount": null
    }
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Batch delete coupons (/docs/api/coupons/batch-delete-coupons)

Delete multiple coupons in one request by sending the coupon IDs in `resources`.

## DELETE /v2/coupons/batch

Batch delete coupons

Soft-delete multiple coupons by sending their IDs in `resources`. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.v2BatchDeleteCoupons({
  "resources": [1, 2]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.v2_batch_delete_coupons(resources=[1, 2])
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->v2BatchDeleteCoupons(resources: [1, 2]);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsV2BatchDeleteCouponsParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[1,2]}"), params); err != nil { panic(err) }
    if err := client.Coupons().V2BatchDeleteCoupons(context.Background(), params); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.Coupons.V2BatchDeleteCouponsAsync(new CouponsV2BatchDeleteCouponsOptions
    {
        Resources = JsonConvert.DeserializeObject<List<long>>("[1,2]")!,
    });
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.v2BatchDeleteCoupons(resources = listOf(1L, 2L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.v2_batch_delete_coupons(resources: [1, 2])
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::V2BatchDeleteCouponsParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2BatchDeleteCouponsParams::new(serde_json::from_str("{\"resources\":[1,2]}")?);
    let result = client.coupons().v_2_batch_delete_coupons(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.v2_batch_delete_coupons(client, %{"resources" => [1, 2]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons v-2-batch-delete-coupons --body '{"resources":[1,2]}' --yes

```

- Method: `DELETE`

- Path: `/v2/coupons/batch`

- Full URL: `https://sell.app/api/v2/coupons/batch`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v2/coupons/batch" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    1,
    2
  ]
}'
```

## Path Parameters
None.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "integer"
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    1,
    2
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": "string"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "store_wide": {
            "type": "boolean"
          },
          "minimum_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
            "example": "2026-07-03 12:15:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "maximum_discount_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
          },
          "products": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "discount",
          "limit",
          "store_wide",
          "minimum_amount",
          "expires_at",
          "created_at",
          "updated_at",
          "store_id",
          "deleted_at",
          "maximum_discount_amount",
          "products",
          "product_variants"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "code": "BONANZA",
      "type": "PERCENTAGE",
      "discount": "80",
      "limit": null,
      "store_wide": true,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "deleted_at": "2026-08-30T12:00:01.000000Z",
      "products": [],
      "product_variants": [],
      "maximum_discount_amount": null
    },
    {
      "id": 2,
      "code": "BONANZA2",
      "type": "PERCENTAGE",
      "discount": "80",
      "limit": null,
      "store_wide": true,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "deleted_at": "2026-08-30T12:00:01.000000Z",
      "products": [],
      "product_variants": [],
      "maximum_discount_amount": null
    }
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Batch update coupons (/docs/api/coupons/batch-update-coupons)

Update multiple coupons in one request by sending a `resources` object keyed by coupon ID.

Each update supports `products` and `product_variants`. Omit `product_variants` to preserve a coupon's existing variant restrictions, or send an empty array to make all variants of its selected products eligible.

```json
{
  "resources": {
    "1": {
      "store_wide": false,
      "products": [123],
      "product_variants": [1001, 1002]
    }
  }
}
```

## PATCH /v2/coupons/batch

Batch update coupons

Update multiple coupons in one request by sending a `resources` object keyed by coupon ID. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.v2BatchUpdateCoupons({
  "resources": {"1": {"store_wide":false,"products":[123],"product_variants":[1001,1002]}}
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.v2_batch_update_coupons(
    resources={
        "1": {"store_wide": False, "products": [123], "product_variants": [1001, 1002]}
    }
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->v2BatchUpdateCoupons(
    resources: [
        '1' => ['store_wide' => false, 'products' => [123], 'product_variants' => [1001, 1002]],
    ],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsV2BatchUpdateCouponsParams{}
    if err := json.Unmarshal([]byte("{\"resources\":{\"1\":{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}}}"), params); err != nil { panic(err) }
    result, err := client.Coupons().V2BatchUpdateCoupons(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.V2BatchUpdateCouponsAsync(new CouponsV2BatchUpdateCouponsOptions
    {
        Resources = JsonConvert.DeserializeObject<V2BatchUpdateCouponsRequestApplicationJsonPropertyResources>("{\"1\":{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}}")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.v2BatchUpdateCoupons(resources = ObjectMapperFactory.read("{\"1\":{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}}", app.sell.sellapp.models.V2BatchUpdateCouponsRequestApplicationJsonPropertyResources::class.java))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.v2_batch_update_coupons(
  resources: {
    "1" => { store_wide: false, products: [123], product_variants: [1001, 1002] }
  }
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::V2BatchUpdateCouponsParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2BatchUpdateCouponsParams::new(serde_json::from_str("{\"resources\":{\"1\":{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}}}")?);
    let result = client.coupons().v_2_batch_update_coupons(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.v2_batch_update_coupons(client, %{"resources" => %{"1" => %{"store_wide" => false, "products" => [123], "product_variants" => [1001, 1002]}}})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons v-2-batch-update-coupons --body '{"resources":{"1":{"store_wide":false,"products":[123],"product_variants":[1001,1002]}}}' --yes

```

- Method: `PATCH`

- Path: `/v2/coupons/batch`

- Full URL: `https://sell.app/api/v2/coupons/batch`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/coupons/batch" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": {
    "1": {
      "store_wide": false,
      "products": [
        123
      ],
      "product_variants": [
        1001,
        1002
      ]
    }
  }
}'
```

## Path Parameters
None.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, optional): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 255
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": [
              "number",
              "string"
            ],
            "minimum": 1,
            "maxLength": 255,
            "description": "A decimal discount value of at least 1. Percentage discounts cannot exceed 100; amount discounts use the store currency's major unit."
          },
          "store_wide": {
            "type": "boolean"
          },
          "products": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "integer"
            },
            "description": "Product IDs the coupon applies to when store_wide is false."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Optional variant restrictions. Omit to preserve existing restrictions or send an empty array to allow every variant of the selected products."
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "A future date and time, or null for no expiry."
          },
          "minimum_amount": {
            "type": [
              "number",
              "string",
              "null"
            ],
            "minimum": 1,
            "maxLength": 255,
            "description": "A decimal minimum order amount in the store currency's major unit, or null for no minimum."
          }
        }
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": {
    "1": {
      "store_wide": false,
      "products": [
        123
      ],
      "product_variants": [
        1001,
        1002
      ]
    }
  }
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": "string"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "store_wide": {
            "type": "boolean"
          },
          "minimum_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
            "example": "2026-07-03 12:15:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "maximum_discount_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
          },
          "products": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "discount",
          "limit",
          "store_wide",
          "minimum_amount",
          "expires_at",
          "created_at",
          "updated_at",
          "store_id",
          "deleted_at",
          "maximum_discount_amount",
          "products",
          "product_variants"
        ]
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "code": "BONANZA",
      "type": "PERCENTAGE",
      "discount": "80",
      "limit": null,
      "store_wide": false,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2026-08-30T12:00:01.000000Z",
      "store_id": 1,
      "deleted_at": null,
      "products": [
        123
      ],
      "product_variants": [
        1001,
        1002
      ],
      "maximum_discount_amount": null
    }
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Create a coupon (/docs/api/coupons/create-a-coupon)

Create a discount code for your store.

## POST /v2/coupons

Create a coupon

Create a discount code for your store. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.v2CreateCoupon({
  "code": "PLAN10",
  "type": "PERCENTAGE",
  "discount": 10,
  "storeWide": false,
  "products": [123, 456],
  "productVariants": [1001, 1002]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.v2_create_coupon(
    code="PLAN10",
    type="PERCENTAGE",
    discount=10,
    store_wide=False,
    products=[123, 456],
    product_variants=[1001, 1002]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->v2CreateCoupon(
    code: 'PLAN10',
    type: 'PERCENTAGE',
    discount: 10,
    storeWide: false,
    products: [123, 456],
    productVariants: [1001, 1002],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsV2CreateCouponParams{}
    if err := json.Unmarshal([]byte("{\"code\":\"PLAN10\",\"type\":\"PERCENTAGE\",\"discount\":10,\"store_wide\":false,\"products\":[123,456],\"product_variants\":[1001,1002]}"), params); err != nil { panic(err) }
    result, err := client.Coupons().V2CreateCoupon(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.V2CreateCouponAsync(new CouponsV2CreateCouponOptions
    {
        Code = "PLAN10",
        Type = JsonConvert.DeserializeObject<SdkV2CreateCouponRequestApplicationJsonType>("\"PERCENTAGE\"")!,
        Discount = JsonConvert.DeserializeObject<OneOf.OneOf<double, string>>("10")!,
        StoreWide = false,
        Products = JsonConvert.DeserializeObject<List<long>>("[123,456]")!,
        ProductVariants = JsonConvert.DeserializeObject<List<long>>("[1001,1002]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.v2CreateCoupon(code = "PLAN10", type = app.sell.sellapp.types.SdkCreateCouponRequestApplicationJsonType("PERCENTAGE"), discount = 10, storeWide = false, products = listOf(123L, 456L), productVariants = listOf(1001L, 1002L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.v2_create_coupon(
  code: "PLAN10",
  type: "PERCENTAGE",
  discount: 10,
  store_wide: false,
  products: [123, 456],
  product_variants: [1001, 1002]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::V2CreateCouponParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2CreateCouponParams::new(serde_json::from_str("{\"code\":\"PLAN10\",\"type\":\"PERCENTAGE\",\"discount\":10,\"store_wide\":false,\"products\":[123,456],\"product_variants\":[1001,1002]}")?);
    let result = client.coupons().v_2_create_coupon(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.v2_create_coupon(client, %{"code" => "PLAN10", "type" => "PERCENTAGE", "discount" => 10, "store_wide" => false, "products" => [123, 456], "product_variants" => [1001, 1002]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons v-2-create-coupon --body '{"code":"PLAN10","type":"PERCENTAGE","discount":10,"store_wide":false,"products":[123,456],"product_variants":[1001,1002]}' --yes

```

- Method: `POST`

- Path: `/v2/coupons`

- Full URL: `https://sell.app/api/v2/coupons`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/coupons" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "code": "PLAN10",
  "type": "PERCENTAGE",
  "discount": 10,
  "store_wide": false,
  "products": [
    123,
    456
  ],
  "product_variants": [
    1001,
    1002
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, optional): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "code": {
      "type": "string",
      "maxLength": 255
    },
    "type": {
      "type": "string",
      "enum": [
        "PERCENTAGE",
        "AMOUNT"
      ]
    },
    "discount": {
      "type": [
        "number",
        "string"
      ],
      "minimum": 1,
      "maxLength": 255,
      "description": "A decimal discount value of at least 1. Percentage discounts cannot exceed 100; amount discounts use the store currency's major unit."
    },
    "store_wide": {
      "type": "boolean"
    },
    "products": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "integer"
      },
      "description": "Product IDs the coupon applies to when store_wide is false."
    },
    "product_variants": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "description": "Optional variant restrictions. Every variant must belong to a selected product. Products without listed variants remain eligible on all variants."
    },
    "limit": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "expires_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "A future date and time, or null for no expiry."
    },
    "minimum_amount": {
      "type": [
        "number",
        "string",
        "null"
      ],
      "minimum": 1,
      "maxLength": 255,
      "description": "A decimal minimum order amount in the store currency's major unit, or null for no minimum."
    }
  },
  "required": [
    "code",
    "type",
    "discount",
    "store_wide"
  ]
}
```

Example:

```json
{
  "code": "PLAN10",
  "type": "PERCENTAGE",
  "discount": 10,
  "store_wide": false,
  "products": [
    123,
    456
  ],
  "product_variants": [
    1001,
    1002
  ]
}
```

## Responses

### 201

Coupon created successfully.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "code": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "enum": [
            "PERCENTAGE",
            "AMOUNT"
          ]
        },
        "discount": {
          "type": "string"
        },
        "limit": {
          "type": [
            "integer",
            "null"
          ]
        },
        "store_wide": {
          "type": "boolean"
        },
        "minimum_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
          "example": "2026-07-03 12:15:00"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "maximum_discount_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
        },
        "products": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
        },
        "product_variants": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
        }
      },
      "required": [
        "id",
        "code",
        "type",
        "discount",
        "limit",
        "store_wide",
        "minimum_amount",
        "expires_at",
        "created_at",
        "updated_at",
        "store_id",
        "deleted_at",
        "maximum_discount_amount",
        "products",
        "product_variants"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "code": "PLAN10",
    "type": "PERCENTAGE",
    "discount": "10",
    "limit": null,
    "store_wide": false,
    "minimum_amount": null,
    "expires_at": null,
    "created_at": "2026-08-30T12:00:01.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "store_id": 1,
    "deleted_at": null,
    "products": [
      123,
      456
    ],
    "product_variants": [
      1001,
      1002
    ],
    "maximum_discount_amount": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

## Limit a coupon to specific products or variants [#limit-a-coupon-to-specific-products-or-variants]

Set `store_wide` to `false` and include a `products` array containing the product IDs the coupon should apply to.

Optionally include `product_variants` to restrict any selected product to particular variants. Every variant ID must belong to one of the products in `products`. If a selected product has no IDs in `product_variants`, the coupon applies to all of that product's current and future variants.

```json
{
  "code": "PLAN10",
  "type": "PERCENTAGE",
  "discount": 10,
  "store_wide": false,
  "products": [123, 456],
  "product_variants": [1001, 1002]
}
```

In this example, product `123` is limited to variants `1001` and `1002`, while product `456` accepts the coupon on every variant. When `store_wide` is `true`, the API ignores product and variant scoping.

# Delete a coupon (/docs/api/coupons/delete-a-coupon)

Soft-delete a coupon. The response includes its `deleted_at` timestamp.

Use `with_trashed` or `only_trashed` when retrieving deleted coupons.

## DELETE /v2/coupons/{coupon}

Delete a coupon

Soft-delete a coupon. The returned coupon includes its deleted_at timestamp; use with_trashed or only_trashed to retrieve soft-deleted coupons later. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.v2DeleteCoupon({
  "coupon": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.v2_delete_coupon(coupon=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->v2DeleteCoupon(coupon: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsV2DeleteCouponParams{}
    if err := client.Coupons().V2DeleteCoupon(context.Background(), 1, params); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.Coupons.V2DeleteCouponAsync(
    "1",
    new CouponsV2DeleteCouponOptions
    {
    }
);
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.v2DeleteCoupon(coupon = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.v2_delete_coupon(coupon: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::V2DeleteCouponParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2DeleteCouponParams::default();
    let result = client.coupons().v_2_delete_coupon("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.v2_delete_coupon(client, 1, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons v-2-delete-coupon 1 --yes

```

- Method: `DELETE`

- Path: `/v2/coupons/{coupon}`

- Full URL: `https://sell.app/api/v2/coupons/{coupon}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COUPON_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v2/coupons/${SELLAPP_COUPON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `coupon` (`integer`, required): The coupon path parameter.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "code": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "enum": [
            "PERCENTAGE",
            "AMOUNT"
          ]
        },
        "discount": {
          "type": "string"
        },
        "limit": {
          "type": [
            "integer",
            "null"
          ]
        },
        "store_wide": {
          "type": "boolean"
        },
        "minimum_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
          "example": "2026-07-03 12:15:00"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "maximum_discount_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
        },
        "products": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
        },
        "product_variants": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
        }
      },
      "required": [
        "id",
        "code",
        "type",
        "discount",
        "limit",
        "store_wide",
        "minimum_amount",
        "expires_at",
        "created_at",
        "updated_at",
        "store_id",
        "deleted_at",
        "maximum_discount_amount",
        "products",
        "product_variants"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "code": "BONANZA",
    "type": "PERCENTAGE",
    "discount": "80",
    "limit": null,
    "store_wide": true,
    "minimum_amount": null,
    "expires_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "store_id": 1,
    "deleted_at": "2026-08-30T12:00:01.000000Z",
    "products": [],
    "product_variants": [],
    "maximum_discount_amount": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Overview (/docs/api/coupons)



Coupons apply an amount or percentage discount when a customer supplies a code.
Choose which products qualify, how often the code can be used, and when it is
valid. For discounts that apply without a code, use [Promotions](/api/promotions).

The response fields `products` and `product_variants` contain explicit product
and variant IDs that determine where the coupon applies.

Coupons and their linked products must belong to the selected store. Track
batch requests in your integration and check what changed after a lost response
before retrying; batch writes do not have a general idempotency guarantee.
Each endpoint documents its discount units, limits, and date fields.

## Endpoints [#endpoints]

* [List coupons](/api/coupons/list-all-coupons)
* [Search coupons](/api/coupons/search-coupons)
* [Create a coupon](/api/coupons/create-a-coupon)
* [Batch create coupons](/api/coupons/batch-create-coupons)
* [Retrieve a coupon](/api/coupons/retrieve-a-coupon)
* [Update a coupon](/api/coupons/update-a-coupon)
* [Batch update coupons](/api/coupons/batch-update-coupons)
* [Batch delete coupons](/api/coupons/batch-delete-coupons)
* [Delete a coupon](/api/coupons/delete-a-coupon)


# List all coupons (/docs/api/coupons/list-all-coupons)

List your store's coupons, 15 per page by default.

## GET /v2/coupons

List all coupons

List your store's coupons, 15 per page by default. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.v2ListCoupons({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.v2_list_coupons()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->v2ListCoupons();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsV2ListCouponsParams{}
    page := client.Coupons().V2ListCoupons(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.V2ListCouponsAsync(new CouponsV2ListCouponsOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.v2ListCoupons()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.v2_list_coupons
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::V2ListCouponsParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2ListCouponsParams::default();
    let result = client.coupons().v_2_list_coupons(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.v2_list_coupons(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons v-2-list-coupons

```

- Method: `GET`

- Path: `/v2/coupons`

- Full URL: `https://sell.app/api/v2/coupons`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/coupons" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": "string"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "store_wide": {
            "type": "boolean"
          },
          "minimum_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
            "example": "2026-07-03 12:15:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "maximum_discount_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
          },
          "products": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "discount",
          "limit",
          "store_wide",
          "minimum_amount",
          "expires_at",
          "created_at",
          "updated_at",
          "store_id",
          "deleted_at",
          "maximum_discount_amount",
          "products",
          "product_variants"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "code": "BONANZA",
      "type": "PERCENTAGE",
      "discount": "80",
      "limit": null,
      "store_wide": true,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "deleted_at": null,
      "products": [],
      "product_variants": [],
      "maximum_discount_amount": null
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/coupons?page=1",
    "last": "https://sell.app/api/v2/coupons?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/coupons",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/coupons?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve a coupon (/docs/api/coupons/retrieve-a-coupon)

Retrieve a coupon by its ID.

## GET /v2/coupons/{coupon}

Retrieve a coupon

Retrieve a coupon by its ID. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.v2GetCoupon({
  "coupon": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.v2_get_coupon(coupon=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->v2GetCoupon(coupon: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsV2GetCouponParams{}
    result, err := client.Coupons().V2GetCoupon(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.V2GetCouponAsync(
    "1",
    new CouponsV2GetCouponOptions
    {
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.v2GetCoupon(coupon = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.v2_get_coupon(coupon: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::V2GetCouponParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2GetCouponParams::default();
    let result = client.coupons().v_2_get_coupon("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.v2_get_coupon(client, 1, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons v-2-get-coupon 1

```

- Method: `GET`

- Path: `/v2/coupons/{coupon}`

- Full URL: `https://sell.app/api/v2/coupons/{coupon}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COUPON_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/coupons/${SELLAPP_COUPON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `coupon` (`integer`, required): The coupon path parameter.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "code": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "enum": [
            "PERCENTAGE",
            "AMOUNT"
          ]
        },
        "discount": {
          "type": "string"
        },
        "limit": {
          "type": [
            "integer",
            "null"
          ]
        },
        "store_wide": {
          "type": "boolean"
        },
        "minimum_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
          "example": "2026-07-03 12:15:00"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "maximum_discount_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
        },
        "products": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
        },
        "product_variants": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
        }
      },
      "required": [
        "id",
        "code",
        "type",
        "discount",
        "limit",
        "store_wide",
        "minimum_amount",
        "expires_at",
        "created_at",
        "updated_at",
        "store_id",
        "deleted_at",
        "maximum_discount_amount",
        "products",
        "product_variants"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "code": "BONANZA",
    "type": "PERCENTAGE",
    "discount": "80",
    "limit": null,
    "store_wide": true,
    "minimum_amount": null,
    "expires_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "deleted_at": null,
    "products": [],
    "product_variants": [],
    "maximum_discount_amount": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Search coupons (/docs/api/coupons/search-coupons)

Search coupons with filters, search terms, includes, and sort instructions in a JSON request body.

## POST /v2/coupons/search

Search coupons

Search coupons using JSON body filters, search terms, includes, and sort instructions. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.v2SearchCoupons({
  "filters": [{"field": "id", "operator": "=", "value": 1}],
  "sort": [{"field": "created_at", "direction": "desc"}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.v2_search_coupons(
    filters=[{"field": "id", "operator": "=", "value": 1}],
    sort=[{"field": "created_at", "direction": "desc"}]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->v2SearchCoupons(
    filters: [['field' => 'id', 'operator' => '=', 'value' => 1]],
    sort: [['field' => 'created_at', 'direction' => 'desc']],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsV2SearchCouponsParams{}
    if err := json.Unmarshal([]byte("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}"), params); err != nil { panic(err) }
    page := client.Coupons().V2SearchCoupons(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.V2SearchCouponsAsync(new CouponsV2SearchCouponsOptions
    {
        Filters = JsonConvert.DeserializeObject<List<V2SearchCouponsRequestApplicationJsonPropertyFiltersItem>>("[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}]")!,
        Sort = JsonConvert.DeserializeObject<List<V2SearchCouponsRequestApplicationJsonPropertySortItem>>("[{\"field\":\"created_at\",\"direction\":\"desc\"}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.v2SearchCoupons(filters = listOf(ObjectMapperFactory.read("{\"field\":\"id\",\"operator\":\"=\",\"value\":1}", app.sell.sellapp.models.V2SearchCouponsRequestApplicationJsonPropertyFiltersItem::class.java)), sort = listOf(ObjectMapperFactory.read("{\"field\":\"created_at\",\"direction\":\"desc\"}", app.sell.sellapp.models.V2SearchCouponsRequestApplicationJsonPropertySortItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.v2_search_coupons(
  filters: [{ field: "id", operator: "=", value: 1 }],
  sort: [{ field: "created_at", direction: "desc" }]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::V2SearchCouponsParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2SearchCouponsParams::new(serde_json::from_str("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}")?);
    let result = client.coupons().v_2_search_coupons(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.v2_search_coupons(client, %{"filters" => [%{"field" => "id", "operator" => "=", "value" => 1}], "sort" => [%{"field" => "created_at", "direction" => "desc"}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons v-2-search-coupons --body '{"filters":[{"field":"id","operator":"=","value":1}],"sort":[{"field":"created_at","direction":"desc"}]}'

```

- Method: `POST`

- Path: `/v2/coupons/search`

- Full URL: `https://sell.app/api/v2/coupons/search`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/coupons/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, optional): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "operator": {
            "type": "string",
            "default": "="
          },
          "value": {},
          "type": {
            "type": "string",
            "enum": [
              "and",
              "or"
            ],
            "default": "and"
          },
          "nested": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "anyOf": [
          {
            "required": [
              "field"
            ]
          },
          {
            "required": [
              "nested"
            ]
          }
        ]
      }
    },
    "sort": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "default": "asc"
          }
        },
        "required": [
          "field"
        ]
      }
    },
    "search": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "null"
          ]
        },
        "case_sensitive": {
          "type": "boolean"
        }
      }
    },
    "includes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "relation": {
            "type": "string"
          }
        },
        "required": [
          "relation"
        ]
      }
    }
  }
}
```

Example:

```json
{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "PERCENTAGE",
              "AMOUNT"
            ]
          },
          "discount": {
            "type": "string"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "store_wide": {
            "type": "boolean"
          },
          "minimum_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
            "example": "2026-07-03 12:15:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "maximum_discount_amount": {
            "type": [
              "string",
              "null"
            ],
            "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
          },
          "products": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
          },
          "product_variants": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
          }
        },
        "required": [
          "id",
          "code",
          "type",
          "discount",
          "limit",
          "store_wide",
          "minimum_amount",
          "expires_at",
          "created_at",
          "updated_at",
          "store_id",
          "deleted_at",
          "maximum_discount_amount",
          "products",
          "product_variants"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "code": "BONANZA",
      "type": "PERCENTAGE",
      "discount": "80",
      "limit": null,
      "store_wide": true,
      "minimum_amount": null,
      "expires_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "deleted_at": null,
      "products": [],
      "product_variants": [],
      "maximum_discount_amount": null
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/coupons/search?page=1",
    "last": "https://sell.app/api/v2/coupons/search?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/coupons/search",
    "per_page": 20,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/coupons/search?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Update a coupon (/docs/api/coupons/update-a-coupon)

Change a coupon's discount, limits, or eligible products.

To scope a coupon, set `store_wide` to `false`, send product/listing IDs in `products`, and optionally send variant IDs in `product_variants`. Every variant must belong to one of the selected products.

Omitting `product_variants` preserves existing variant restrictions. Sending an empty `product_variants` array clears the restrictions, making every variant of the selected products eligible. Changing `products` automatically removes restrictions for products that are no longer selected.

## PATCH /v2/coupons/{coupon}

Update a coupon

Change a coupon's discount, limits, or eligible products. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.v2UpdateCoupon({
  "coupon": 1,
  "storeWide": false,
  "products": [123],
  "productVariants": [1001, 1002]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.v2_update_coupon(
    coupon=1,
    store_wide=False,
    products=[123],
    product_variants=[1001, 1002]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->v2UpdateCoupon(
    coupon: 1,
    storeWide: false,
    products: [123],
    productVariants: [1001, 1002],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsV2UpdateCouponParams{}
    if err := json.Unmarshal([]byte("{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}"), params); err != nil { panic(err) }
    result, err := client.Coupons().V2UpdateCoupon(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.V2UpdateCouponAsync(
    "1",
    new CouponsV2UpdateCouponOptions
    {
        StoreWide = false,
        Products = JsonConvert.DeserializeObject<List<long>>("[123]")!,
        ProductVariants = JsonConvert.DeserializeObject<List<long>>("[1001,1002]")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.v2UpdateCoupon(coupon = "1", storeWide = app.sell.sellapp.common.http.PatchField.Present(false), products = app.sell.sellapp.common.http.PatchField.Present(listOf(123L)), productVariants = app.sell.sellapp.common.http.PatchField.Present(listOf(1001L, 1002L)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.v2_update_coupon(
  coupon: 1,
  store_wide: false,
  products: [123],
  product_variants: [1001, 1002]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::V2UpdateCouponParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2UpdateCouponParams::new(serde_json::from_str("{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}")?);
    let result = client.coupons().v_2_update_coupon("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.v2_update_coupon(client, 1, %{"store_wide" => false, "products" => [123], "product_variants" => [1001, 1002]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons v-2-update-coupon 1 --body '{"store_wide":false,"products":[123],"product_variants":[1001,1002]}' --yes

```

- Method: `PATCH`

- Path: `/v2/coupons/{coupon}`

- Full URL: `https://sell.app/api/v2/coupons/{coupon}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COUPON_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/coupons/${SELLAPP_COUPON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "store_wide": false,
  "products": [
    123
  ],
  "product_variants": [
    1001,
    1002
  ]
}'
```

## Path Parameters
- `coupon` (`integer`, required): The coupon path parameter.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "code": {
      "type": "string",
      "maxLength": 255
    },
    "type": {
      "type": "string",
      "enum": [
        "PERCENTAGE",
        "AMOUNT"
      ]
    },
    "discount": {
      "type": [
        "number",
        "string"
      ],
      "minimum": 1,
      "maxLength": 255,
      "description": "A decimal discount value of at least 1. Percentage discounts cannot exceed 100; amount discounts use the store currency's major unit."
    },
    "store_wide": {
      "type": "boolean"
    },
    "products": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "integer"
      },
      "description": "Product IDs the coupon applies to when store_wide is false."
    },
    "product_variants": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "description": "Optional variant restrictions. Omit to preserve existing restrictions or send an empty array to allow every variant of the selected products."
    },
    "limit": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "expires_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "A future date and time, or null for no expiry."
    },
    "minimum_amount": {
      "type": [
        "number",
        "string",
        "null"
      ],
      "minimum": 1,
      "maxLength": 255,
      "description": "A decimal minimum order amount in the store currency's major unit, or null for no minimum."
    }
  }
}
```

Example:

```json
{
  "store_wide": false,
  "products": [
    123
  ],
  "product_variants": [
    1001,
    1002
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "code": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "enum": [
            "PERCENTAGE",
            "AMOUNT"
          ]
        },
        "discount": {
          "type": "string"
        },
        "limit": {
          "type": [
            "integer",
            "null"
          ]
        },
        "store_wide": {
          "type": "boolean"
        },
        "minimum_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
          "example": "2026-07-03 12:15:00"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "maximum_discount_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
        },
        "products": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
        },
        "product_variants": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
        }
      },
      "required": [
        "id",
        "code",
        "type",
        "discount",
        "limit",
        "store_wide",
        "minimum_amount",
        "expires_at",
        "created_at",
        "updated_at",
        "store_id",
        "deleted_at",
        "maximum_discount_amount",
        "products",
        "product_variants"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "code": "BAZINGA",
    "type": "PERCENTAGE",
    "discount": "80",
    "limit": null,
    "store_wide": false,
    "minimum_amount": null,
    "expires_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "store_id": 1,
    "deleted_at": null,
    "products": [
      123
    ],
    "product_variants": [
      1001,
      1002
    ],
    "maximum_discount_amount": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PUT /v2/coupons/{coupon}

Update a coupon

Change a coupon's discount, limits, or eligible products. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coupons.v2ReplaceCoupon({
  "coupon": 1,
  "storeWide": false,
  "products": [123],
  "productVariants": [1001, 1002]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.coupons.v2_replace_coupon(
    coupon=1,
    store_wide=False,
    products=[123],
    product_variants=[1001, 1002]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coupons()->v2ReplaceCoupon(
    coupon: 1,
    storeWide: false,
    products: [123],
    productVariants: [1001, 1002],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CouponsV2ReplaceCouponParams{}
    if err := json.Unmarshal([]byte("{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}"), params); err != nil { panic(err) }
    result, err := client.Coupons().V2ReplaceCoupon(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Coupons.V2ReplaceCouponAsync(
    "1",
    new CouponsV2ReplaceCouponOptions
    {
        StoreWide = false,
        Products = JsonConvert.DeserializeObject<List<long>>("[123]")!,
        ProductVariants = JsonConvert.DeserializeObject<List<long>>("[1001,1002]")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coupons.v2ReplaceCoupon(coupon = "1", storeWide = false, products = listOf(123L), productVariants = listOf(1001L, 1002L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.coupons.v2_replace_coupon(
  coupon: 1,
  store_wide: false,
  products: [123],
  product_variants: [1001, 1002]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::coupons::V2ReplaceCouponParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2ReplaceCouponParams::new(serde_json::from_str("{\"store_wide\":false,\"products\":[123],\"product_variants\":[1001,1002]}")?);
    let result = client.coupons().v_2_replace_coupon("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Coupons.v2_replace_coupon(client, 1, %{"store_wide" => false, "products" => [123], "product_variants" => [1001, 1002]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp coupons v-2-replace-coupon 1 --body '{"store_wide":false,"products":[123],"product_variants":[1001,1002]}' --yes

```

- Method: `PUT`

- Path: `/v2/coupons/{coupon}`

- Full URL: `https://sell.app/api/v2/coupons/{coupon}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COUPON_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/coupons/${SELLAPP_COUPON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "store_wide": false,
  "products": [
    123
  ],
  "product_variants": [
    1001,
    1002
  ]
}'
```

## Path Parameters
- `coupon` (`integer`, required): The coupon path parameter.

## Query Parameters
- `with_trashed` (`boolean`, optional): Include soft-deleted resources in the result.
- `only_trashed` (`boolean`, optional): Return only soft-deleted resources. Ignored when with_trashed is true.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "code": {
      "type": "string",
      "maxLength": 255
    },
    "type": {
      "type": "string",
      "enum": [
        "PERCENTAGE",
        "AMOUNT"
      ]
    },
    "discount": {
      "type": [
        "number",
        "string"
      ],
      "minimum": 1,
      "maxLength": 255,
      "description": "A decimal discount value of at least 1. Percentage discounts cannot exceed 100; amount discounts use the store currency's major unit."
    },
    "store_wide": {
      "type": "boolean"
    },
    "products": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "integer"
      },
      "description": "Product IDs the coupon applies to when store_wide is false."
    },
    "product_variants": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "description": "Optional variant restrictions. Omit to preserve existing restrictions or send an empty array to allow every variant of the selected products."
    },
    "limit": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "expires_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "A future date and time, or null for no expiry."
    },
    "minimum_amount": {
      "type": [
        "number",
        "string",
        "null"
      ],
      "minimum": 1,
      "maxLength": 255,
      "description": "A decimal minimum order amount in the store currency's major unit, or null for no minimum."
    }
  }
}
```

Example:

```json
{
  "store_wide": false,
  "products": [
    123
  ],
  "product_variants": [
    1001,
    1002
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "code": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "enum": [
            "PERCENTAGE",
            "AMOUNT"
          ]
        },
        "discount": {
          "type": "string"
        },
        "limit": {
          "type": [
            "integer",
            "null"
          ]
        },
        "store_wide": {
          "type": "boolean"
        },
        "minimum_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The decimal minimum order amount in the store currency's major unit, or null when no minimum applies."
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the coupon stops applying, as a `Y-m-d H:i:s` timestamp in the store timezone, or null when it never expires. Unlike the other timestamps in this API, this is not an ISO 8601 instant.",
          "example": "2026-07-03 12:15:00"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "maximum_discount_amount": {
          "type": [
            "string",
            "null"
          ],
          "description": "The maximum decimal discount in the store currency's major unit for percentage coupons. This field is managed from the dashboard and is read-only in the v1 Coupons API."
        },
        "products": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Product IDs this coupon applies to. Store-wide coupons return an empty array."
        },
        "product_variants": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "Variant IDs explicitly included in the coupon scope. An empty array means all variants of the selected products are eligible."
        }
      },
      "required": [
        "id",
        "code",
        "type",
        "discount",
        "limit",
        "store_wide",
        "minimum_amount",
        "expires_at",
        "created_at",
        "updated_at",
        "store_id",
        "deleted_at",
        "maximum_discount_amount",
        "products",
        "product_variants"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "code": "BAZINGA",
    "type": "PERCENTAGE",
    "discount": "80",
    "limit": null,
    "store_wide": false,
    "minimum_amount": null,
    "expires_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "store_id": 1,
    "deleted_at": null,
    "products": [
      123
    ],
    "product_variants": [
      1001,
      1002
    ],
    "maximum_discount_amount": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Overview (/docs/api/courses)



A course combines a product listing, one variant, and a curriculum. Use the course API for sections, lessons, and access settings; use the [products API](/api/products) to create or delete the course product itself.

Use an API key with the `listing` ability or OAuth with `products:read` for reads and `products:write` for mutations. Send `X-STORE`; current store permissions also apply. Courses and their sections, lessons, questions, answers, attachments, and videos must be in the selected store.

## Endpoints [#endpoints]

* [List courses](/api/courses/list-courses)
* [Search courses](/api/courses/search-courses)
* [Retrieve a course](/api/courses/retrieve-course)
* [Update a course](/api/courses/update-course)
* [Manage course sections](/api/courses/manage-course-sections)
* [Reorder course sections](/api/courses/reorder-course-sections)
* [Manage course lessons](/api/courses/manage-course-lessons)
* [Reorder course lessons](/api/courses/reorder-course-lessons)

## Curriculum ordering [#curriculum-ordering]

To reorder sections or lessons, send the complete list of current IDs, each exactly once. A lesson entry also names its destination section. The move happens as one change, so a lesson does not end up missing or listed twice.

## Draft and publication behavior [#draft-and-publication-behavior]

`is_published` controls whether an individual lesson is available to enrolled customers. Course `visibility` controls the listing. Setting visibility to `PUBLIC` requires a ready promotional video and at least one published lesson; otherwise the API returns `422` and preserves the draft.

## Optimistic writes [#optimistic-writes]

Someone may edit a course while your app is still holding an older copy. Send the `updated_at` you last read as `expected_updated_at` to catch this. If the resource changed, the API returns `422` without applying your edit. Retrieve it again, review the newer content, and then decide whether to retry.

## Compatibility boundaries [#compatibility-boundaries]

The existing public course preview endpoint is unchanged. Preview sources continue to use ready promotional videos and video lessons marked `is_preview`; curriculum administration does not expose signed playback tokens.

Course titles, descriptions, lessons, quiz prompts, and assignment instructions remain in the language you write them; they are not interface translation keys.


# List courses (/docs/api/courses/list-courses)

## GET /v2/courses

List courses

List course products and their complete ordered curriculum for the authenticated store. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.courses.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->courses()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CoursesListParams{}
    page := client.Courses().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Courses.ListAsync(new CoursesListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.courses.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.courses().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Courses.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses list

```

- Method: `GET`

- Path: `/v2/courses`

- Full URL: `https://sell.app/api/v2/courses`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/courses" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching items in one data array without pagination links or metadata.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ]
              },
              "is_draft": {
                "type": "boolean"
              },
              "delivery_text": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "category": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "development",
                  "business",
                  "marketing",
                  "design",
                  "finance",
                  "it-software",
                  "personal-development",
                  "productivity",
                  "other",
                  null
                ]
              },
              "level": {
                "type": "string",
                "enum": [
                  "all_levels",
                  "beginner",
                  "intermediate",
                  "advanced"
                ]
              },
              "language": {
                "type": "string"
              },
              "subtitle": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "author": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "subcategory": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "what_you_learn": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "requirements": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "certificate_enabled": {
                "type": "boolean"
              },
              "access_type": {
                "type": "string",
                "enum": [
                  "lifetime",
                  "limited"
                ]
              },
              "access_duration_days": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 1,
                "maximum": 3650
              },
              "enrollment_limit": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 1
              },
              "promo_video": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "mux_playback_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "mux_status": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "duration_seconds": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 0
                      }
                    },
                    "required": [
                      "mux_playback_id",
                      "mux_status",
                      "duration_seconds"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "sections": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "lessons": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "section_id": {
                            "type": "integer"
                          },
                          "title": {
                            "type": "string"
                          },
                          "content": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "lecture",
                              "video",
                              "text",
                              "quiz",
                              "assignment"
                            ]
                          },
                          "is_preview": {
                            "type": "boolean"
                          },
                          "is_published": {
                            "type": "boolean"
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "video": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "source": {
                                    "type": "string",
                                    "enum": [
                                      "mux",
                                      "external"
                                    ]
                                  },
                                  "external_url": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "format": "uri"
                                  },
                                  "mux_playback_id": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "mux_status": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "duration_seconds": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ],
                                    "minimum": 0
                                  }
                                },
                                "required": [
                                  "source",
                                  "external_url",
                                  "mux_playback_id",
                                  "mux_status",
                                  "duration_seconds"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "attachments": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "title": {
                                  "type": "string"
                                },
                                "mime_type": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "size_bytes": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ],
                                  "minimum": 0
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                }
                              },
                              "required": [
                                "id",
                                "title",
                                "mime_type",
                                "size_bytes",
                                "sort_order"
                              ]
                            }
                          },
                          "assignment": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "estimated_duration_minutes": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ],
                                    "minimum": 1,
                                    "maximum": 1440
                                  },
                                  "instructions": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "questions": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "id": {
                                          "type": "integer"
                                        },
                                        "prompt": {
                                          "type": "string"
                                        },
                                        "question_type": {
                                          "type": "string",
                                          "enum": [
                                            "text",
                                            "single_choice",
                                            "multiple_choice"
                                          ]
                                        },
                                        "solution": {
                                          "type": [
                                            "string",
                                            "null"
                                          ]
                                        },
                                        "sort_order": {
                                          "type": "integer",
                                          "minimum": 1
                                        },
                                        "answers": {
                                          "type": "array",
                                          "items": {
                                            "type": "object",
                                            "properties": {
                                              "id": {
                                                "type": "integer"
                                              },
                                              "answer": {
                                                "type": "string"
                                              },
                                              "is_correct": {
                                                "type": "boolean"
                                              },
                                              "sort_order": {
                                                "type": "integer",
                                                "minimum": 1
                                              }
                                            },
                                            "required": [
                                              "id",
                                              "answer",
                                              "is_correct",
                                              "sort_order"
                                            ]
                                          }
                                        },
                                        "created_at": {
                                          "type": "string",
                                          "format": "date-time"
                                        },
                                        "updated_at": {
                                          "type": "string",
                                          "format": "date-time"
                                        }
                                      },
                                      "required": [
                                        "id",
                                        "prompt",
                                        "question_type",
                                        "solution",
                                        "sort_order",
                                        "answers",
                                        "created_at",
                                        "updated_at"
                                      ]
                                    }
                                  }
                                },
                                "required": [
                                  "estimated_duration_minutes",
                                  "instructions",
                                  "questions"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "questions": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "prompt": {
                                  "type": "string"
                                },
                                "question_type": {
                                  "type": "string",
                                  "enum": [
                                    "text",
                                    "single_choice",
                                    "multiple_choice"
                                  ]
                                },
                                "solution": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                },
                                "answers": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "id": {
                                        "type": "integer"
                                      },
                                      "answer": {
                                        "type": "string"
                                      },
                                      "is_correct": {
                                        "type": "boolean"
                                      },
                                      "sort_order": {
                                        "type": "integer",
                                        "minimum": 1
                                      }
                                    },
                                    "required": [
                                      "id",
                                      "answer",
                                      "is_correct",
                                      "sort_order"
                                    ]
                                  }
                                },
                                "created_at": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "updated_at": {
                                  "type": "string",
                                  "format": "date-time"
                                }
                              },
                              "required": [
                                "id",
                                "prompt",
                                "question_type",
                                "solution",
                                "sort_order",
                                "answers",
                                "created_at",
                                "updated_at"
                              ]
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "section_id",
                          "title",
                          "content",
                          "type",
                          "is_preview",
                          "is_published",
                          "sort_order",
                          "video",
                          "attachments",
                          "assignment",
                          "questions",
                          "created_at",
                          "updated_at"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "description",
                    "sort_order",
                    "lessons",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "title",
              "slug",
              "description",
              "visibility",
              "is_draft",
              "delivery_text",
              "category",
              "level",
              "language",
              "subtitle",
              "author",
              "subcategory",
              "what_you_learn",
              "requirements",
              "certificate_enabled",
              "access_type",
              "access_duration_days",
              "enrollment_limit",
              "promo_video",
              "sections",
              "created_at",
              "updated_at"
            ]
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ]
              },
              "is_draft": {
                "type": "boolean"
              },
              "delivery_text": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "category": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "development",
                  "business",
                  "marketing",
                  "design",
                  "finance",
                  "it-software",
                  "personal-development",
                  "productivity",
                  "other",
                  null
                ]
              },
              "level": {
                "type": "string",
                "enum": [
                  "all_levels",
                  "beginner",
                  "intermediate",
                  "advanced"
                ]
              },
              "language": {
                "type": "string"
              },
              "subtitle": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "author": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "subcategory": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "what_you_learn": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "requirements": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "certificate_enabled": {
                "type": "boolean"
              },
              "access_type": {
                "type": "string",
                "enum": [
                  "lifetime",
                  "limited"
                ]
              },
              "access_duration_days": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 1,
                "maximum": 3650
              },
              "enrollment_limit": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 1
              },
              "promo_video": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "mux_playback_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "mux_status": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "duration_seconds": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 0
                      }
                    },
                    "required": [
                      "mux_playback_id",
                      "mux_status",
                      "duration_seconds"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "sections": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "lessons": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "section_id": {
                            "type": "integer"
                          },
                          "title": {
                            "type": "string"
                          },
                          "content": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "lecture",
                              "video",
                              "text",
                              "quiz",
                              "assignment"
                            ]
                          },
                          "is_preview": {
                            "type": "boolean"
                          },
                          "is_published": {
                            "type": "boolean"
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "video": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "source": {
                                    "type": "string",
                                    "enum": [
                                      "mux",
                                      "external"
                                    ]
                                  },
                                  "external_url": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "format": "uri"
                                  },
                                  "mux_playback_id": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "mux_status": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "duration_seconds": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ],
                                    "minimum": 0
                                  }
                                },
                                "required": [
                                  "source",
                                  "external_url",
                                  "mux_playback_id",
                                  "mux_status",
                                  "duration_seconds"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "attachments": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "title": {
                                  "type": "string"
                                },
                                "mime_type": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "size_bytes": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ],
                                  "minimum": 0
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                }
                              },
                              "required": [
                                "id",
                                "title",
                                "mime_type",
                                "size_bytes",
                                "sort_order"
                              ]
                            }
                          },
                          "assignment": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "estimated_duration_minutes": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ],
                                    "minimum": 1,
                                    "maximum": 1440
                                  },
                                  "instructions": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "questions": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "id": {
                                          "type": "integer"
                                        },
                                        "prompt": {
                                          "type": "string"
                                        },
                                        "question_type": {
                                          "type": "string",
                                          "enum": [
                                            "text",
                                            "single_choice",
                                            "multiple_choice"
                                          ]
                                        },
                                        "solution": {
                                          "type": [
                                            "string",
                                            "null"
                                          ]
                                        },
                                        "sort_order": {
                                          "type": "integer",
                                          "minimum": 1
                                        },
                                        "answers": {
                                          "type": "array",
                                          "items": {
                                            "type": "object",
                                            "properties": {
                                              "id": {
                                                "type": "integer"
                                              },
                                              "answer": {
                                                "type": "string"
                                              },
                                              "is_correct": {
                                                "type": "boolean"
                                              },
                                              "sort_order": {
                                                "type": "integer",
                                                "minimum": 1
                                              }
                                            },
                                            "required": [
                                              "id",
                                              "answer",
                                              "is_correct",
                                              "sort_order"
                                            ]
                                          }
                                        },
                                        "created_at": {
                                          "type": "string",
                                          "format": "date-time"
                                        },
                                        "updated_at": {
                                          "type": "string",
                                          "format": "date-time"
                                        }
                                      },
                                      "required": [
                                        "id",
                                        "prompt",
                                        "question_type",
                                        "solution",
                                        "sort_order",
                                        "answers",
                                        "created_at",
                                        "updated_at"
                                      ]
                                    }
                                  }
                                },
                                "required": [
                                  "estimated_duration_minutes",
                                  "instructions",
                                  "questions"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "questions": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "prompt": {
                                  "type": "string"
                                },
                                "question_type": {
                                  "type": "string",
                                  "enum": [
                                    "text",
                                    "single_choice",
                                    "multiple_choice"
                                  ]
                                },
                                "solution": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                },
                                "answers": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "id": {
                                        "type": "integer"
                                      },
                                      "answer": {
                                        "type": "string"
                                      },
                                      "is_correct": {
                                        "type": "boolean"
                                      },
                                      "sort_order": {
                                        "type": "integer",
                                        "minimum": 1
                                      }
                                    },
                                    "required": [
                                      "id",
                                      "answer",
                                      "is_correct",
                                      "sort_order"
                                    ]
                                  }
                                },
                                "created_at": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "updated_at": {
                                  "type": "string",
                                  "format": "date-time"
                                }
                              },
                              "required": [
                                "id",
                                "prompt",
                                "question_type",
                                "solution",
                                "sort_order",
                                "answers",
                                "created_at",
                                "updated_at"
                              ]
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "section_id",
                          "title",
                          "content",
                          "type",
                          "is_preview",
                          "is_published",
                          "sort_order",
                          "video",
                          "attachments",
                          "assignment",
                          "questions",
                          "created_at",
                          "updated_at"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "description",
                    "sort_order",
                    "lessons",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "title",
              "slug",
              "description",
              "visibility",
              "is_draft",
              "delivery_text",
              "category",
              "level",
              "language",
              "subtitle",
              "author",
              "subcategory",
              "what_you_learn",
              "requirements",
              "certificate_enabled",
              "access_type",
              "access_duration_days",
              "enrollment_limit",
              "promo_video",
              "sections",
              "created_at",
              "updated_at"
            ]
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example (minimal):

```json
{
  "data": [
    {
      "id": 50,
      "title": "Design foundations",
      "slug": "design-foundations",
      "description": "Build your first design with reusable templates.",
      "visibility": "HIDDEN",
      "is_draft": false,
      "delivery_text": "Open your course to get started.",
      "category": "design",
      "level": "all_levels",
      "language": "en",
      "subtitle": null,
      "author": "Launch Lab",
      "subcategory": null,
      "what_you_learn": [
        "Customize a reusable template."
      ],
      "requirements": [
        "A web browser."
      ],
      "certificate_enabled": false,
      "access_type": "lifetime",
      "access_duration_days": null,
      "enrollment_limit": null,
      "promo_video": null,
      "sections": [
        {
          "id": 51,
          "title": "Getting started",
          "description": "Your first project.",
          "sort_order": 1,
          "lessons": [
            {
              "id": 52,
              "section_id": 51,
              "title": "Build your first design",
              "content": "Choose a template and add your project details.",
              "type": "lecture",
              "is_preview": false,
              "is_published": false,
              "sort_order": 1,
              "video": null,
              "attachments": [],
              "assignment": null,
              "questions": [],
              "created_at": "2026-09-01T12:00:00Z",
              "updated_at": "2026-09-01T12:00:00Z"
            }
          ],
          "created_at": "2026-09-01T12:00:00Z",
          "updated_at": "2026-09-01T12:00:00Z"
        }
      ],
      "created_at": "2026-09-01T12:00:00Z",
      "updated_at": "2026-09-01T12:00:00Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/courses?page=1",
    "last": "https://sell.app/api/v2/courses?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/courses?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ],
    "path": "https://sell.app/api/v2/courses",
    "per_page": 15,
    "to": 1,
    "total": 1
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Manage course lessons (/docs/api/courses/manage-course-lessons)

Lesson types are `lecture`, `video`, `text`, `quiz`, and `assignment`. A new lecture placeholder can become a video or text lesson; other established types cannot be changed. Rich text is cleaned before storage to remove unsafe markup.

Quiz and assignment arrays replace the corresponding structured question set when present. `is_preview` applies only to video lessons. `is_published` controls enrolled-customer visibility independently from the course listing visibility.

Video fields in responses are references to existing Mux or external video records. Upload lifecycle and signed playback tokens remain in the existing dashboard and preview flows.

## PATCH /v2/courses/{course}/lessons/{lesson}

Update a course lesson

Update lesson content, draft state, preview state, or replace the structured quiz or assignment body. Item type is immutable except while choosing video or text for a new lecture placeholder. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coursesLessons.update({
  "course": "string_example",
  "lesson": 1,
  "title": "Welcome",
  "isPublished": false
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses_lessons.update(
    course="string_example",
    lesson=1,
    title="Welcome",
    is_published=False
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coursesLessons()->update(
    course: 'string_example',
    lesson: 1,
    title: 'Welcome',
    isPublished: false,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CoursesLessonsUpdateParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Welcome\",\"is_published\":false}"), params); err != nil { panic(err) }
    result, err := client.CoursesLessons().Update(context.Background(), "string_example", 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CoursesLessons.UpdateAsync(
    "string_example",
    "1",
    new CoursesLessonsUpdateOptions
    {
        Title = "Welcome",
        IsPublished = false,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coursesLessons.update(course = "string_example", lesson = "1", title = app.sell.sellapp.common.http.PatchField.Present("Welcome"), isPublished = app.sell.sellapp.common.http.PatchField.Present(false))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses_lessons.update(
  course: "string_example",
  lesson: 1,
  title: "Welcome",
  is_published: false
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses_lessons::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{\"title\":\"Welcome\",\"is_published\":false}")?);
    let result = client.courses_lessons().update("string_example", "1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CoursesLessons.update(client, "string_example", 1, %{"title" => "Welcome", "is_published" => false})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses lessons update --course test_course 1 --title Welcome --is-published false

```

- Method: `PATCH`

- Path: `/v2/courses/{course}/lessons/{lesson}`

- Full URL: `https://sell.app/api/v2/courses/{course}/lessons/{lesson}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COURSE_ID='replace-me'
export SELLAPP_LESSON_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/${SELLAPP_COURSE_ID}/lessons/${SELLAPP_LESSON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Welcome",
  "is_published": false
}'
```

## Path Parameters
- `course` (`string`, required): The course path parameter.
- `lesson` (`integer`, required): The lesson path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255
    },
    "type": {
      "type": "string",
      "enum": [
        "lecture",
        "video",
        "text",
        "quiz",
        "assignment"
      ]
    },
    "content": {
      "type": [
        "string",
        "null"
      ]
    },
    "is_preview": {
      "type": "boolean",
      "description": "Preview is available only for video lessons."
    },
    "is_published": {
      "type": "boolean"
    },
    "assignment": {
      "type": "object",
      "properties": {
        "estimated_duration_minutes": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1,
          "maximum": 1440
        },
        "instructions": {
          "type": [
            "string",
            "null"
          ]
        },
        "questions": {
          "type": "array",
          "maxItems": 12,
          "items": {
            "type": "object",
            "properties": {
              "prompt": {
                "type": "string",
                "maxLength": 65535
              },
              "solution": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 65535
              }
            },
            "required": [
              "prompt"
            ]
          }
        }
      }
    },
    "questions": {
      "type": "array",
      "maxItems": 12,
      "items": {
        "type": "object",
        "properties": {
          "prompt": {
            "type": "string",
            "maxLength": 65535
          },
          "question_type": {
            "type": "string",
            "enum": [
              "text",
              "single_choice",
              "multiple_choice"
            ]
          },
          "solution": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 65535
          },
          "answers": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "object",
              "properties": {
                "answer": {
                  "type": "string",
                  "maxLength": 65535
                },
                "is_correct": {
                  "type": "boolean"
                }
              },
              "required": [
                "answer",
                "is_correct"
              ]
            }
          }
        },
        "required": [
          "prompt",
          "question_type"
        ]
      }
    },
    "expected_updated_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
```

Example (minimal):

```json
{
  "title": "Welcome",
  "is_published": false
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "section_id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "content": {
          "type": [
            "string",
            "null"
          ]
        },
        "type": {
          "type": "string",
          "enum": [
            "lecture",
            "video",
            "text",
            "quiz",
            "assignment"
          ]
        },
        "is_preview": {
          "type": "boolean"
        },
        "is_published": {
          "type": "boolean"
        },
        "sort_order": {
          "type": "integer",
          "minimum": 1
        },
        "video": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "source": {
                  "type": "string",
                  "enum": [
                    "mux",
                    "external"
                  ]
                },
                "external_url": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uri"
                },
                "mux_playback_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "mux_status": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "duration_seconds": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                }
              },
              "required": [
                "source",
                "external_url",
                "mux_playback_id",
                "mux_status",
                "duration_seconds"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "attachments": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "mime_type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "size_bytes": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              }
            },
            "required": [
              "id",
              "title",
              "mime_type",
              "size_bytes",
              "sort_order"
            ]
          }
        },
        "assignment": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "estimated_duration_minutes": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 1,
                  "maximum": 1440
                },
                "instructions": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "questions": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "prompt": {
                        "type": "string"
                      },
                      "question_type": {
                        "type": "string",
                        "enum": [
                          "text",
                          "single_choice",
                          "multiple_choice"
                        ]
                      },
                      "solution": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "sort_order": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "answers": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer"
                            },
                            "answer": {
                              "type": "string"
                            },
                            "is_correct": {
                              "type": "boolean"
                            },
                            "sort_order": {
                              "type": "integer",
                              "minimum": 1
                            }
                          },
                          "required": [
                            "id",
                            "answer",
                            "is_correct",
                            "sort_order"
                          ]
                        }
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "updated_at": {
                        "type": "string",
                        "format": "date-time"
                      }
                    },
                    "required": [
                      "id",
                      "prompt",
                      "question_type",
                      "solution",
                      "sort_order",
                      "answers",
                      "created_at",
                      "updated_at"
                    ]
                  }
                }
              },
              "required": [
                "estimated_duration_minutes",
                "instructions",
                "questions"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "questions": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "prompt": {
                "type": "string"
              },
              "question_type": {
                "type": "string",
                "enum": [
                  "text",
                  "single_choice",
                  "multiple_choice"
                ]
              },
              "solution": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              },
              "answers": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "answer": {
                      "type": "string"
                    },
                    "is_correct": {
                      "type": "boolean"
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    }
                  },
                  "required": [
                    "id",
                    "answer",
                    "is_correct",
                    "sort_order"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "prompt",
              "question_type",
              "solution",
              "sort_order",
              "answers",
              "created_at",
              "updated_at"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "section_id",
        "title",
        "content",
        "type",
        "is_preview",
        "is_published",
        "sort_order",
        "video",
        "attachments",
        "assignment",
        "questions",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 52,
    "section_id": 51,
    "title": "Welcome",
    "content": "Choose a template and add your project details.",
    "type": "lecture",
    "is_preview": false,
    "is_published": false,
    "sort_order": 1,
    "video": null,
    "attachments": [],
    "assignment": null,
    "questions": [],
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PUT /v2/courses/{course}/lessons/{lesson}

Update a course lesson

Update lesson content, draft state, preview state, or replace the structured quiz or assignment body. Item type is immutable except while choosing video or text for a new lecture placeholder. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coursesLessons.replace({
  "course": "string_example",
  "lesson": 1,
  "title": "Welcome",
  "isPublished": false
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses_lessons.replace(
    course="string_example",
    lesson=1,
    title="Welcome",
    is_published=False
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coursesLessons()->replace(
    course: 'string_example',
    lesson: 1,
    title: 'Welcome',
    isPublished: false,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CoursesLessonsReplaceParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Welcome\",\"is_published\":false}"), params); err != nil { panic(err) }
    result, err := client.CoursesLessons().Replace(context.Background(), "string_example", 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CoursesLessons.ReplaceAsync(
    "string_example",
    "1",
    new CoursesLessonsReplaceOptions
    {
        Title = "Welcome",
        IsPublished = false,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coursesLessons.replace(course = "string_example", lesson = "1", title = "Welcome", isPublished = false)
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses_lessons.replace(
  course: "string_example",
  lesson: 1,
  title: "Welcome",
  is_published: false
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses_lessons::ReplaceParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceParams::new(serde_json::from_str("{\"title\":\"Welcome\",\"is_published\":false}")?);
    let result = client.courses_lessons().replace("string_example", "1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CoursesLessons.replace(client, "string_example", 1, %{"title" => "Welcome", "is_published" => false})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses lessons replace --course test_course 1 --title Welcome --is-published false

```

- Method: `PUT`

- Path: `/v2/courses/{course}/lessons/{lesson}`

- Full URL: `https://sell.app/api/v2/courses/{course}/lessons/{lesson}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COURSE_ID='replace-me'
export SELLAPP_LESSON_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/${SELLAPP_COURSE_ID}/lessons/${SELLAPP_LESSON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Welcome",
  "is_published": false
}'
```

## Path Parameters
- `course` (`string`, required): The course path parameter.
- `lesson` (`integer`, required): The lesson path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255
    },
    "type": {
      "type": "string",
      "enum": [
        "lecture",
        "video",
        "text",
        "quiz",
        "assignment"
      ]
    },
    "content": {
      "type": [
        "string",
        "null"
      ]
    },
    "is_preview": {
      "type": "boolean",
      "description": "Preview is available only for video lessons."
    },
    "is_published": {
      "type": "boolean"
    },
    "assignment": {
      "type": "object",
      "properties": {
        "estimated_duration_minutes": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1,
          "maximum": 1440
        },
        "instructions": {
          "type": [
            "string",
            "null"
          ]
        },
        "questions": {
          "type": "array",
          "maxItems": 12,
          "items": {
            "type": "object",
            "properties": {
              "prompt": {
                "type": "string",
                "maxLength": 65535
              },
              "solution": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 65535
              }
            },
            "required": [
              "prompt"
            ]
          }
        }
      }
    },
    "questions": {
      "type": "array",
      "maxItems": 12,
      "items": {
        "type": "object",
        "properties": {
          "prompt": {
            "type": "string",
            "maxLength": 65535
          },
          "question_type": {
            "type": "string",
            "enum": [
              "text",
              "single_choice",
              "multiple_choice"
            ]
          },
          "solution": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 65535
          },
          "answers": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "object",
              "properties": {
                "answer": {
                  "type": "string",
                  "maxLength": 65535
                },
                "is_correct": {
                  "type": "boolean"
                }
              },
              "required": [
                "answer",
                "is_correct"
              ]
            }
          }
        },
        "required": [
          "prompt",
          "question_type"
        ]
      }
    },
    "expected_updated_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
```

Example (minimal):

```json
{
  "title": "Welcome",
  "is_published": false
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "section_id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "content": {
          "type": [
            "string",
            "null"
          ]
        },
        "type": {
          "type": "string",
          "enum": [
            "lecture",
            "video",
            "text",
            "quiz",
            "assignment"
          ]
        },
        "is_preview": {
          "type": "boolean"
        },
        "is_published": {
          "type": "boolean"
        },
        "sort_order": {
          "type": "integer",
          "minimum": 1
        },
        "video": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "source": {
                  "type": "string",
                  "enum": [
                    "mux",
                    "external"
                  ]
                },
                "external_url": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uri"
                },
                "mux_playback_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "mux_status": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "duration_seconds": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                }
              },
              "required": [
                "source",
                "external_url",
                "mux_playback_id",
                "mux_status",
                "duration_seconds"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "attachments": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "mime_type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "size_bytes": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              }
            },
            "required": [
              "id",
              "title",
              "mime_type",
              "size_bytes",
              "sort_order"
            ]
          }
        },
        "assignment": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "estimated_duration_minutes": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 1,
                  "maximum": 1440
                },
                "instructions": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "questions": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "prompt": {
                        "type": "string"
                      },
                      "question_type": {
                        "type": "string",
                        "enum": [
                          "text",
                          "single_choice",
                          "multiple_choice"
                        ]
                      },
                      "solution": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "sort_order": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "answers": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer"
                            },
                            "answer": {
                              "type": "string"
                            },
                            "is_correct": {
                              "type": "boolean"
                            },
                            "sort_order": {
                              "type": "integer",
                              "minimum": 1
                            }
                          },
                          "required": [
                            "id",
                            "answer",
                            "is_correct",
                            "sort_order"
                          ]
                        }
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "updated_at": {
                        "type": "string",
                        "format": "date-time"
                      }
                    },
                    "required": [
                      "id",
                      "prompt",
                      "question_type",
                      "solution",
                      "sort_order",
                      "answers",
                      "created_at",
                      "updated_at"
                    ]
                  }
                }
              },
              "required": [
                "estimated_duration_minutes",
                "instructions",
                "questions"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "questions": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "prompt": {
                "type": "string"
              },
              "question_type": {
                "type": "string",
                "enum": [
                  "text",
                  "single_choice",
                  "multiple_choice"
                ]
              },
              "solution": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              },
              "answers": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "answer": {
                      "type": "string"
                    },
                    "is_correct": {
                      "type": "boolean"
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    }
                  },
                  "required": [
                    "id",
                    "answer",
                    "is_correct",
                    "sort_order"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "prompt",
              "question_type",
              "solution",
              "sort_order",
              "answers",
              "created_at",
              "updated_at"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "section_id",
        "title",
        "content",
        "type",
        "is_preview",
        "is_published",
        "sort_order",
        "video",
        "attachments",
        "assignment",
        "questions",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 52,
    "section_id": 51,
    "title": "Welcome",
    "content": "Choose a template and add your project details.",
    "type": "lecture",
    "is_preview": false,
    "is_published": false,
    "sort_order": 1,
    "video": null,
    "attachments": [],
    "assignment": null,
    "questions": [],
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## DELETE /v2/courses/{course}/lessons/{lesson}

Delete a course lesson

Delete a lesson and its structured questions, assignment, attachments, and video reference, then normalize lesson order. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coursesLessons.delete({
  "course": "string_example",
  "lesson": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses_lessons.delete(
    course="string_example",
    lesson=1
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coursesLessons()->delete(
    course: 'string_example',
    lesson: 1,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    if err := client.CoursesLessons().Delete(context.Background(), "string_example", 1); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.CoursesLessons.DeleteAsync(
    "string_example",
    "1"
);
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coursesLessons.delete(course = "string_example", lesson = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses_lessons.delete(
  course: "string_example",
  lesson: 1
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses_lessons::DeleteParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = DeleteParams::default();
    let result = client.courses_lessons().delete("string_example", "1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CoursesLessons.delete(client, "string_example", 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses lessons delete --course test_course 1 --yes

```

- Method: `DELETE`

- Path: `/v2/courses/{course}/lessons/{lesson}`

- Full URL: `https://sell.app/api/v2/courses/{course}/lessons/{lesson}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COURSE_ID='replace-me'
export SELLAPP_LESSON_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/${SELLAPP_COURSE_ID}/lessons/${SELLAPP_LESSON_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `course` (`string`, required): The course path parameter.
- `lesson` (`integer`, required): The lesson path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "section_id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "content": {
          "type": [
            "string",
            "null"
          ]
        },
        "type": {
          "type": "string",
          "enum": [
            "lecture",
            "video",
            "text",
            "quiz",
            "assignment"
          ]
        },
        "is_preview": {
          "type": "boolean"
        },
        "is_published": {
          "type": "boolean"
        },
        "sort_order": {
          "type": "integer",
          "minimum": 1
        },
        "video": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "source": {
                  "type": "string",
                  "enum": [
                    "mux",
                    "external"
                  ]
                },
                "external_url": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uri"
                },
                "mux_playback_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "mux_status": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "duration_seconds": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                }
              },
              "required": [
                "source",
                "external_url",
                "mux_playback_id",
                "mux_status",
                "duration_seconds"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "attachments": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "mime_type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "size_bytes": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              }
            },
            "required": [
              "id",
              "title",
              "mime_type",
              "size_bytes",
              "sort_order"
            ]
          }
        },
        "assignment": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "estimated_duration_minutes": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 1,
                  "maximum": 1440
                },
                "instructions": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "questions": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "prompt": {
                        "type": "string"
                      },
                      "question_type": {
                        "type": "string",
                        "enum": [
                          "text",
                          "single_choice",
                          "multiple_choice"
                        ]
                      },
                      "solution": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "sort_order": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "answers": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer"
                            },
                            "answer": {
                              "type": "string"
                            },
                            "is_correct": {
                              "type": "boolean"
                            },
                            "sort_order": {
                              "type": "integer",
                              "minimum": 1
                            }
                          },
                          "required": [
                            "id",
                            "answer",
                            "is_correct",
                            "sort_order"
                          ]
                        }
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "updated_at": {
                        "type": "string",
                        "format": "date-time"
                      }
                    },
                    "required": [
                      "id",
                      "prompt",
                      "question_type",
                      "solution",
                      "sort_order",
                      "answers",
                      "created_at",
                      "updated_at"
                    ]
                  }
                }
              },
              "required": [
                "estimated_duration_minutes",
                "instructions",
                "questions"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "questions": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "prompt": {
                "type": "string"
              },
              "question_type": {
                "type": "string",
                "enum": [
                  "text",
                  "single_choice",
                  "multiple_choice"
                ]
              },
              "solution": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              },
              "answers": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "answer": {
                      "type": "string"
                    },
                    "is_correct": {
                      "type": "boolean"
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    }
                  },
                  "required": [
                    "id",
                    "answer",
                    "is_correct",
                    "sort_order"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "prompt",
              "question_type",
              "solution",
              "sort_order",
              "answers",
              "created_at",
              "updated_at"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "section_id",
        "title",
        "content",
        "type",
        "is_preview",
        "is_published",
        "sort_order",
        "video",
        "attachments",
        "assignment",
        "questions",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 52,
    "section_id": 51,
    "title": "Build your first design",
    "content": "Choose a template and add your project details.",
    "type": "lecture",
    "is_preview": false,
    "is_published": false,
    "sort_order": 1,
    "video": null,
    "attachments": [],
    "assignment": null,
    "questions": [],
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Manage course sections (/docs/api/courses/manage-course-sections)

New sections append to the curriculum. Deleting a section also deletes its lessons and nested assignment, quiz, attachment, and video records, then closes remaining order gaps.

## POST /v2/courses/{course}/sections

Create a course section

Append a section to a course curriculum. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coursesSections.create({
  "course": "string_example",
  "title": "Getting started"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses_sections.create(
    course="string_example",
    title="Getting started"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coursesSections()->create(
    course: 'string_example',
    title: 'Getting started',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CoursesSectionsCreateParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Getting started\"}"), params); err != nil { panic(err) }
    result, err := client.CoursesSections().Create(context.Background(), "string_example", params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CoursesSections.CreateAsync(
    "string_example",
    new CoursesSectionsCreateOptions
    {
        Title = "Getting started",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coursesSections.create(course = "string_example", title = "Getting started")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses_sections.create(
  course: "string_example",
  title: "Getting started"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses_sections::CreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateParams::new(serde_json::from_str("{\"title\":\"Getting started\"}")?);
    let result = client.courses_sections().create("string_example", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CoursesSections.create(client, "string_example", %{"title" => "Getting started"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses sections create test_course --title 'Getting started'

```

- Method: `POST`

- Path: `/v2/courses/{course}/sections`

- Full URL: `https://sell.app/api/v2/courses/{course}/sections`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COURSE_ID='replace-me'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/${SELLAPP_COURSE_ID}/sections" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Getting started"
}'
```

## Path Parameters
- `course` (`string`, required): The course path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255
    },
    "description": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 65535
    }
  },
  "required": [
    "title"
  ]
}
```

Example (minimal):

```json
{
  "title": "Getting started"
}
```

## Responses

### 201

Course section created.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "sort_order": {
          "type": "integer",
          "minimum": 1
        },
        "lessons": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "section_id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "content": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "type": {
                "type": "string",
                "enum": [
                  "lecture",
                  "video",
                  "text",
                  "quiz",
                  "assignment"
                ]
              },
              "is_preview": {
                "type": "boolean"
              },
              "is_published": {
                "type": "boolean"
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              },
              "video": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "source": {
                        "type": "string",
                        "enum": [
                          "mux",
                          "external"
                        ]
                      },
                      "external_url": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "uri"
                      },
                      "mux_playback_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "mux_status": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "duration_seconds": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 0
                      }
                    },
                    "required": [
                      "source",
                      "external_url",
                      "mux_playback_id",
                      "mux_status",
                      "duration_seconds"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "attachments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "mime_type": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "size_bytes": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "minimum": 0
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "mime_type",
                    "size_bytes",
                    "sort_order"
                  ]
                }
              },
              "assignment": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "estimated_duration_minutes": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 1,
                        "maximum": 1440
                      },
                      "instructions": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "questions": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer"
                            },
                            "prompt": {
                              "type": "string"
                            },
                            "question_type": {
                              "type": "string",
                              "enum": [
                                "text",
                                "single_choice",
                                "multiple_choice"
                              ]
                            },
                            "solution": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "sort_order": {
                              "type": "integer",
                              "minimum": 1
                            },
                            "answers": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "integer"
                                  },
                                  "answer": {
                                    "type": "string"
                                  },
                                  "is_correct": {
                                    "type": "boolean"
                                  },
                                  "sort_order": {
                                    "type": "integer",
                                    "minimum": 1
                                  }
                                },
                                "required": [
                                  "id",
                                  "answer",
                                  "is_correct",
                                  "sort_order"
                                ]
                              }
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time"
                            },
                            "updated_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          },
                          "required": [
                            "id",
                            "prompt",
                            "question_type",
                            "solution",
                            "sort_order",
                            "answers",
                            "created_at",
                            "updated_at"
                          ]
                        }
                      }
                    },
                    "required": [
                      "estimated_duration_minutes",
                      "instructions",
                      "questions"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "questions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "prompt": {
                      "type": "string"
                    },
                    "question_type": {
                      "type": "string",
                      "enum": [
                        "text",
                        "single_choice",
                        "multiple_choice"
                      ]
                    },
                    "solution": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "answers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "answer": {
                            "type": "string"
                          },
                          "is_correct": {
                            "type": "boolean"
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          }
                        },
                        "required": [
                          "id",
                          "answer",
                          "is_correct",
                          "sort_order"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "prompt",
                    "question_type",
                    "solution",
                    "sort_order",
                    "answers",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "section_id",
              "title",
              "content",
              "type",
              "is_preview",
              "is_published",
              "sort_order",
              "video",
              "attachments",
              "assignment",
              "questions",
              "created_at",
              "updated_at"
            ]
          },
          "description": "The lessons of the section. Absent from the creation response."
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "title",
        "description",
        "sort_order",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 51,
    "title": "Getting started",
    "description": "Your first project.",
    "sort_order": 1,
    "lessons": [],
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v2/courses/{course}/sections/{section}

Update a course section

Update a section title or sanitized rich-text description. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coursesSections.update({
  "course": "string_example",
  "section": 1,
  "title": "Getting started"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses_sections.update(
    course="string_example",
    section=1,
    title="Getting started"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coursesSections()->update(
    course: 'string_example',
    section: 1,
    title: 'Getting started',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CoursesSectionsUpdateParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Getting started\"}"), params); err != nil { panic(err) }
    result, err := client.CoursesSections().Update(context.Background(), "string_example", 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CoursesSections.UpdateAsync(
    "string_example",
    "1",
    new CoursesSectionsUpdateOptions
    {
        Title = "Getting started",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coursesSections.update(course = "string_example", section = "1", title = app.sell.sellapp.common.http.PatchField.Present("Getting started"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses_sections.update(
  course: "string_example",
  section: 1,
  title: "Getting started"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses_sections::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{\"title\":\"Getting started\"}")?);
    let result = client.courses_sections().update("string_example", "1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CoursesSections.update(client, "string_example", 1, %{"title" => "Getting started"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses sections update --course test_course 1 --title 'Getting started'

```

- Method: `PATCH`

- Path: `/v2/courses/{course}/sections/{section}`

- Full URL: `https://sell.app/api/v2/courses/{course}/sections/{section}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COURSE_ID='replace-me'
export SELLAPP_SECTION_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/${SELLAPP_COURSE_ID}/sections/${SELLAPP_SECTION_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Getting started"
}'
```

## Path Parameters
- `course` (`string`, required): The course path parameter.
- `section` (`integer`, required): The section path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255
    },
    "description": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 65535
    },
    "expected_updated_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
```

Example (minimal):

```json
{
  "title": "Getting started"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "sort_order": {
          "type": "integer",
          "minimum": 1
        },
        "lessons": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "section_id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "content": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "type": {
                "type": "string",
                "enum": [
                  "lecture",
                  "video",
                  "text",
                  "quiz",
                  "assignment"
                ]
              },
              "is_preview": {
                "type": "boolean"
              },
              "is_published": {
                "type": "boolean"
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              },
              "video": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "source": {
                        "type": "string",
                        "enum": [
                          "mux",
                          "external"
                        ]
                      },
                      "external_url": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "uri"
                      },
                      "mux_playback_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "mux_status": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "duration_seconds": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 0
                      }
                    },
                    "required": [
                      "source",
                      "external_url",
                      "mux_playback_id",
                      "mux_status",
                      "duration_seconds"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "attachments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "mime_type": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "size_bytes": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "minimum": 0
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "mime_type",
                    "size_bytes",
                    "sort_order"
                  ]
                }
              },
              "assignment": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "estimated_duration_minutes": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 1,
                        "maximum": 1440
                      },
                      "instructions": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "questions": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer"
                            },
                            "prompt": {
                              "type": "string"
                            },
                            "question_type": {
                              "type": "string",
                              "enum": [
                                "text",
                                "single_choice",
                                "multiple_choice"
                              ]
                            },
                            "solution": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "sort_order": {
                              "type": "integer",
                              "minimum": 1
                            },
                            "answers": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "integer"
                                  },
                                  "answer": {
                                    "type": "string"
                                  },
                                  "is_correct": {
                                    "type": "boolean"
                                  },
                                  "sort_order": {
                                    "type": "integer",
                                    "minimum": 1
                                  }
                                },
                                "required": [
                                  "id",
                                  "answer",
                                  "is_correct",
                                  "sort_order"
                                ]
                              }
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time"
                            },
                            "updated_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          },
                          "required": [
                            "id",
                            "prompt",
                            "question_type",
                            "solution",
                            "sort_order",
                            "answers",
                            "created_at",
                            "updated_at"
                          ]
                        }
                      }
                    },
                    "required": [
                      "estimated_duration_minutes",
                      "instructions",
                      "questions"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "questions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "prompt": {
                      "type": "string"
                    },
                    "question_type": {
                      "type": "string",
                      "enum": [
                        "text",
                        "single_choice",
                        "multiple_choice"
                      ]
                    },
                    "solution": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "answers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "answer": {
                            "type": "string"
                          },
                          "is_correct": {
                            "type": "boolean"
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          }
                        },
                        "required": [
                          "id",
                          "answer",
                          "is_correct",
                          "sort_order"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "prompt",
                    "question_type",
                    "solution",
                    "sort_order",
                    "answers",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "section_id",
              "title",
              "content",
              "type",
              "is_preview",
              "is_published",
              "sort_order",
              "video",
              "attachments",
              "assignment",
              "questions",
              "created_at",
              "updated_at"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "title",
        "description",
        "sort_order",
        "lessons",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 51,
    "title": "Getting started",
    "description": "Your first project.",
    "sort_order": 1,
    "lessons": [
      {
        "id": 52,
        "section_id": 51,
        "title": "Build your first design",
        "content": "Choose a template and add your project details.",
        "type": "lecture",
        "is_preview": false,
        "is_published": false,
        "sort_order": 1,
        "video": null,
        "attachments": [],
        "assignment": null,
        "questions": [],
        "created_at": "2026-09-01T12:00:00Z",
        "updated_at": "2026-09-01T12:00:00Z"
      }
    ],
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PUT /v2/courses/{course}/sections/{section}

Update a course section

Update a section title or sanitized rich-text description. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coursesSections.replace({
  "course": "string_example",
  "section": 1,
  "title": "Getting started"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses_sections.replace(
    course="string_example",
    section=1,
    title="Getting started"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coursesSections()->replace(
    course: 'string_example',
    section: 1,
    title: 'Getting started',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CoursesSectionsReplaceParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Getting started\"}"), params); err != nil { panic(err) }
    result, err := client.CoursesSections().Replace(context.Background(), "string_example", 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CoursesSections.ReplaceAsync(
    "string_example",
    "1",
    new CoursesSectionsReplaceOptions
    {
        Title = "Getting started",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coursesSections.replace(course = "string_example", section = "1", title = "Getting started")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses_sections.replace(
  course: "string_example",
  section: 1,
  title: "Getting started"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses_sections::ReplaceParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceParams::new(serde_json::from_str("{\"title\":\"Getting started\"}")?);
    let result = client.courses_sections().replace("string_example", "1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CoursesSections.replace(client, "string_example", 1, %{"title" => "Getting started"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses sections replace --course test_course 1 --title 'Getting started'

```

- Method: `PUT`

- Path: `/v2/courses/{course}/sections/{section}`

- Full URL: `https://sell.app/api/v2/courses/{course}/sections/{section}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COURSE_ID='replace-me'
export SELLAPP_SECTION_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/${SELLAPP_COURSE_ID}/sections/${SELLAPP_SECTION_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Getting started"
}'
```

## Path Parameters
- `course` (`string`, required): The course path parameter.
- `section` (`integer`, required): The section path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255
    },
    "description": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 65535
    },
    "expected_updated_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
```

Example (minimal):

```json
{
  "title": "Getting started"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "sort_order": {
          "type": "integer",
          "minimum": 1
        },
        "lessons": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "section_id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "content": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "type": {
                "type": "string",
                "enum": [
                  "lecture",
                  "video",
                  "text",
                  "quiz",
                  "assignment"
                ]
              },
              "is_preview": {
                "type": "boolean"
              },
              "is_published": {
                "type": "boolean"
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              },
              "video": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "source": {
                        "type": "string",
                        "enum": [
                          "mux",
                          "external"
                        ]
                      },
                      "external_url": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "uri"
                      },
                      "mux_playback_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "mux_status": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "duration_seconds": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 0
                      }
                    },
                    "required": [
                      "source",
                      "external_url",
                      "mux_playback_id",
                      "mux_status",
                      "duration_seconds"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "attachments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "mime_type": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "size_bytes": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "minimum": 0
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "mime_type",
                    "size_bytes",
                    "sort_order"
                  ]
                }
              },
              "assignment": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "estimated_duration_minutes": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 1,
                        "maximum": 1440
                      },
                      "instructions": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "questions": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer"
                            },
                            "prompt": {
                              "type": "string"
                            },
                            "question_type": {
                              "type": "string",
                              "enum": [
                                "text",
                                "single_choice",
                                "multiple_choice"
                              ]
                            },
                            "solution": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "sort_order": {
                              "type": "integer",
                              "minimum": 1
                            },
                            "answers": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "integer"
                                  },
                                  "answer": {
                                    "type": "string"
                                  },
                                  "is_correct": {
                                    "type": "boolean"
                                  },
                                  "sort_order": {
                                    "type": "integer",
                                    "minimum": 1
                                  }
                                },
                                "required": [
                                  "id",
                                  "answer",
                                  "is_correct",
                                  "sort_order"
                                ]
                              }
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time"
                            },
                            "updated_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          },
                          "required": [
                            "id",
                            "prompt",
                            "question_type",
                            "solution",
                            "sort_order",
                            "answers",
                            "created_at",
                            "updated_at"
                          ]
                        }
                      }
                    },
                    "required": [
                      "estimated_duration_minutes",
                      "instructions",
                      "questions"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "questions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "prompt": {
                      "type": "string"
                    },
                    "question_type": {
                      "type": "string",
                      "enum": [
                        "text",
                        "single_choice",
                        "multiple_choice"
                      ]
                    },
                    "solution": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "answers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "answer": {
                            "type": "string"
                          },
                          "is_correct": {
                            "type": "boolean"
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          }
                        },
                        "required": [
                          "id",
                          "answer",
                          "is_correct",
                          "sort_order"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "prompt",
                    "question_type",
                    "solution",
                    "sort_order",
                    "answers",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "section_id",
              "title",
              "content",
              "type",
              "is_preview",
              "is_published",
              "sort_order",
              "video",
              "attachments",
              "assignment",
              "questions",
              "created_at",
              "updated_at"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "title",
        "description",
        "sort_order",
        "lessons",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 51,
    "title": "Getting started",
    "description": "Your first project.",
    "sort_order": 1,
    "lessons": [
      {
        "id": 52,
        "section_id": 51,
        "title": "Build your first design",
        "content": "Choose a template and add your project details.",
        "type": "lecture",
        "is_preview": false,
        "is_published": false,
        "sort_order": 1,
        "video": null,
        "attachments": [],
        "assignment": null,
        "questions": [],
        "created_at": "2026-09-01T12:00:00Z",
        "updated_at": "2026-09-01T12:00:00Z"
      }
    ],
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## DELETE /v2/courses/{course}/sections/{section}

Delete a course section

Delete a section, its lessons, structured questions, attachments, and video references, then normalize remaining section order. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coursesSections.delete({
  "course": "string_example",
  "section": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses_sections.delete(
    course="string_example",
    section=1
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coursesSections()->delete(
    course: 'string_example',
    section: 1,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    if err := client.CoursesSections().Delete(context.Background(), "string_example", 1); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.CoursesSections.DeleteAsync(
    "string_example",
    "1"
);
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coursesSections.delete(course = "string_example", section = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses_sections.delete(
  course: "string_example",
  section: 1
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses_sections::DeleteParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = DeleteParams::default();
    let result = client.courses_sections().delete("string_example", "1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CoursesSections.delete(client, "string_example", 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses sections delete --course test_course 1 --yes

```

- Method: `DELETE`

- Path: `/v2/courses/{course}/sections/{section}`

- Full URL: `https://sell.app/api/v2/courses/{course}/sections/{section}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COURSE_ID='replace-me'
export SELLAPP_SECTION_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/${SELLAPP_COURSE_ID}/sections/${SELLAPP_SECTION_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `course` (`string`, required): The course path parameter.
- `section` (`integer`, required): The section path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "sort_order": {
          "type": "integer",
          "minimum": 1
        },
        "lessons": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "section_id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "content": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "type": {
                "type": "string",
                "enum": [
                  "lecture",
                  "video",
                  "text",
                  "quiz",
                  "assignment"
                ]
              },
              "is_preview": {
                "type": "boolean"
              },
              "is_published": {
                "type": "boolean"
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              },
              "video": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "source": {
                        "type": "string",
                        "enum": [
                          "mux",
                          "external"
                        ]
                      },
                      "external_url": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "uri"
                      },
                      "mux_playback_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "mux_status": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "duration_seconds": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 0
                      }
                    },
                    "required": [
                      "source",
                      "external_url",
                      "mux_playback_id",
                      "mux_status",
                      "duration_seconds"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "attachments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "mime_type": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "size_bytes": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "minimum": 0
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "mime_type",
                    "size_bytes",
                    "sort_order"
                  ]
                }
              },
              "assignment": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "estimated_duration_minutes": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 1,
                        "maximum": 1440
                      },
                      "instructions": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "questions": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer"
                            },
                            "prompt": {
                              "type": "string"
                            },
                            "question_type": {
                              "type": "string",
                              "enum": [
                                "text",
                                "single_choice",
                                "multiple_choice"
                              ]
                            },
                            "solution": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "sort_order": {
                              "type": "integer",
                              "minimum": 1
                            },
                            "answers": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "integer"
                                  },
                                  "answer": {
                                    "type": "string"
                                  },
                                  "is_correct": {
                                    "type": "boolean"
                                  },
                                  "sort_order": {
                                    "type": "integer",
                                    "minimum": 1
                                  }
                                },
                                "required": [
                                  "id",
                                  "answer",
                                  "is_correct",
                                  "sort_order"
                                ]
                              }
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time"
                            },
                            "updated_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          },
                          "required": [
                            "id",
                            "prompt",
                            "question_type",
                            "solution",
                            "sort_order",
                            "answers",
                            "created_at",
                            "updated_at"
                          ]
                        }
                      }
                    },
                    "required": [
                      "estimated_duration_minutes",
                      "instructions",
                      "questions"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "questions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "prompt": {
                      "type": "string"
                    },
                    "question_type": {
                      "type": "string",
                      "enum": [
                        "text",
                        "single_choice",
                        "multiple_choice"
                      ]
                    },
                    "solution": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "answers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "answer": {
                            "type": "string"
                          },
                          "is_correct": {
                            "type": "boolean"
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          }
                        },
                        "required": [
                          "id",
                          "answer",
                          "is_correct",
                          "sort_order"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "prompt",
                    "question_type",
                    "solution",
                    "sort_order",
                    "answers",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "section_id",
              "title",
              "content",
              "type",
              "is_preview",
              "is_published",
              "sort_order",
              "video",
              "attachments",
              "assignment",
              "questions",
              "created_at",
              "updated_at"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "title",
        "description",
        "sort_order",
        "lessons",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 51,
    "title": "Getting started",
    "description": "Your first project.",
    "sort_order": 1,
    "lessons": [
      {
        "id": 52,
        "section_id": 51,
        "title": "Build your first design",
        "content": "Choose a template and add your project details.",
        "type": "lecture",
        "is_preview": false,
        "is_published": false,
        "sort_order": 1,
        "video": null,
        "attachments": [],
        "assignment": null,
        "questions": [],
        "created_at": "2026-09-01T12:00:00Z",
        "updated_at": "2026-09-01T12:00:00Z"
      }
    ],
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Reorder course lessons (/docs/api/courses/reorder-course-lessons)

Send every lesson ID exactly once with a `section_id` from the same course. Entries appear in request order within each destination section. An invalid list returns `422` without changing any positions.

## PATCH /v2/courses/{course}/lessons/reorder

Reorder course lessons

Replace the complete lesson order and section placement. Send every lesson ID exactly once with a destination section from the same course. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coursesLessons.reorder({
  "course": "string_example",
  "resources": [{"id": 601, "sectionId": 501}, {"id": 602, "sectionId": 501}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses_lessons.reorder(
    course="string_example",
    resources=[{"id": 601, "section_id": 501}, {"id": 602, "section_id": 501}]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coursesLessons()->reorder(
    course: 'string_example',
    resources: [['id' => 601, 'section_id' => 501], ['id' => 602, 'section_id' => 501]],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CoursesLessonsReorderParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[{\"id\":601,\"section_id\":501},{\"id\":602,\"section_id\":501}]}"), params); err != nil { panic(err) }
    result, err := client.CoursesLessons().Reorder(context.Background(), "string_example", params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CoursesLessons.ReorderAsync(
    "string_example",
    new CoursesLessonsReorderOptions
    {
        Resources = JsonConvert.DeserializeObject<List<ReorderCourseLessonsRequestApplicationJsonPropertyResourcesItem>>("[{\"id\":601,\"section_id\":501},{\"id\":602,\"section_id\":501}]")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coursesLessons.reorder(course = "string_example", resources = listOf(ObjectMapperFactory.read("{\"id\":601,\"section_id\":501}", app.sell.sellapp.models.ReorderCourseLessonsRequestApplicationJsonPropertyResourcesItem::class.java), ObjectMapperFactory.read("{\"id\":602,\"section_id\":501}", app.sell.sellapp.models.ReorderCourseLessonsRequestApplicationJsonPropertyResourcesItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses_lessons.reorder(
  course: "string_example",
  resources: [{ id: 601, section_id: 501 }, { id: 602, section_id: 501 }]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses_lessons::ReorderParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReorderParams::new(serde_json::from_str("{\"resources\":[{\"id\":601,\"section_id\":501},{\"id\":602,\"section_id\":501}]}")?);
    let result = client.courses_lessons().reorder("string_example", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CoursesLessons.reorder(client, "string_example", %{"resources" => [%{"id" => 601, "section_id" => 501}, %{"id" => 602, "section_id" => 501}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses lessons reorder test_course --body '{"resources":[{"id":601,"section_id":501},{"id":602,"section_id":501}]}' --yes

```

- Method: `PATCH`

- Path: `/v2/courses/{course}/lessons/reorder`

- Full URL: `https://sell.app/api/v2/courses/{course}/lessons/reorder`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COURSE_ID='replace-me'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/${SELLAPP_COURSE_ID}/lessons/reorder" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    {
      "id": 601,
      "section_id": 501
    },
    {
      "id": 602,
      "section_id": 501
    }
  ]
}'
```

## Path Parameters
- `course` (`string`, required): The course path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "section_id": {
            "type": "integer",
            "minimum": 1
          }
        },
        "required": [
          "id",
          "section_id"
        ]
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example (minimal):

```json
{
  "resources": [
    {
      "id": 601,
      "section_id": 501
    },
    {
      "id": 602,
      "section_id": 501
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ]
        },
        "is_draft": {
          "type": "boolean"
        },
        "delivery_text": {
          "type": [
            "string",
            "null"
          ]
        },
        "category": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "development",
            "business",
            "marketing",
            "design",
            "finance",
            "it-software",
            "personal-development",
            "productivity",
            "other",
            null
          ]
        },
        "level": {
          "type": "string",
          "enum": [
            "all_levels",
            "beginner",
            "intermediate",
            "advanced"
          ]
        },
        "language": {
          "type": "string"
        },
        "subtitle": {
          "type": [
            "string",
            "null"
          ]
        },
        "author": {
          "type": [
            "string",
            "null"
          ]
        },
        "subcategory": {
          "type": [
            "string",
            "null"
          ]
        },
        "what_you_learn": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "requirements": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "certificate_enabled": {
          "type": "boolean"
        },
        "access_type": {
          "type": "string",
          "enum": [
            "lifetime",
            "limited"
          ]
        },
        "access_duration_days": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1,
          "maximum": 3650
        },
        "enrollment_limit": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1
        },
        "promo_video": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "mux_playback_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "mux_status": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "duration_seconds": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                }
              },
              "required": [
                "mux_playback_id",
                "mux_status",
                "duration_seconds"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "sections": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              },
              "lessons": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "section_id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "content": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "lecture",
                        "video",
                        "text",
                        "quiz",
                        "assignment"
                      ]
                    },
                    "is_preview": {
                      "type": "boolean"
                    },
                    "is_published": {
                      "type": "boolean"
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "video": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "source": {
                              "type": "string",
                              "enum": [
                                "mux",
                                "external"
                              ]
                            },
                            "external_url": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "format": "uri"
                            },
                            "mux_playback_id": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "mux_status": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "duration_seconds": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 0
                            }
                          },
                          "required": [
                            "source",
                            "external_url",
                            "mux_playback_id",
                            "mux_status",
                            "duration_seconds"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attachments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "title": {
                            "type": "string"
                          },
                          "mime_type": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "size_bytes": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "minimum": 0
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          }
                        },
                        "required": [
                          "id",
                          "title",
                          "mime_type",
                          "size_bytes",
                          "sort_order"
                        ]
                      }
                    },
                    "assignment": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "estimated_duration_minutes": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 1,
                              "maximum": 1440
                            },
                            "instructions": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "questions": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "integer"
                                  },
                                  "prompt": {
                                    "type": "string"
                                  },
                                  "question_type": {
                                    "type": "string",
                                    "enum": [
                                      "text",
                                      "single_choice",
                                      "multiple_choice"
                                    ]
                                  },
                                  "solution": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "sort_order": {
                                    "type": "integer",
                                    "minimum": 1
                                  },
                                  "answers": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "id": {
                                          "type": "integer"
                                        },
                                        "answer": {
                                          "type": "string"
                                        },
                                        "is_correct": {
                                          "type": "boolean"
                                        },
                                        "sort_order": {
                                          "type": "integer",
                                          "minimum": 1
                                        }
                                      },
                                      "required": [
                                        "id",
                                        "answer",
                                        "is_correct",
                                        "sort_order"
                                      ]
                                    }
                                  },
                                  "created_at": {
                                    "type": "string",
                                    "format": "date-time"
                                  },
                                  "updated_at": {
                                    "type": "string",
                                    "format": "date-time"
                                  }
                                },
                                "required": [
                                  "id",
                                  "prompt",
                                  "question_type",
                                  "solution",
                                  "sort_order",
                                  "answers",
                                  "created_at",
                                  "updated_at"
                                ]
                              }
                            }
                          },
                          "required": [
                            "estimated_duration_minutes",
                            "instructions",
                            "questions"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "questions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "prompt": {
                            "type": "string"
                          },
                          "question_type": {
                            "type": "string",
                            "enum": [
                              "text",
                              "single_choice",
                              "multiple_choice"
                            ]
                          },
                          "solution": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "answers": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "answer": {
                                  "type": "string"
                                },
                                "is_correct": {
                                  "type": "boolean"
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                }
                              },
                              "required": [
                                "id",
                                "answer",
                                "is_correct",
                                "sort_order"
                              ]
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "prompt",
                          "question_type",
                          "solution",
                          "sort_order",
                          "answers",
                          "created_at",
                          "updated_at"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "section_id",
                    "title",
                    "content",
                    "type",
                    "is_preview",
                    "is_published",
                    "sort_order",
                    "video",
                    "attachments",
                    "assignment",
                    "questions",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "title",
              "description",
              "sort_order",
              "lessons",
              "created_at",
              "updated_at"
            ]
          },
          "example": [
            {
              "id": 1,
              "title": "Getting started",
              "description": null,
              "sort_order": 1,
              "lessons": [
                {
                  "id": 1,
                  "section_id": 1,
                  "title": "Welcome to the reading room",
                  "content": "Read the first founder memo.",
                  "type": "lecture",
                  "is_preview": false,
                  "is_published": false,
                  "sort_order": 1,
                  "video": null,
                  "attachments": [],
                  "assignment": null,
                  "questions": [],
                  "created_at": "2026-08-30T12:00:01.000000Z",
                  "updated_at": "2026-08-30T12:00:01.000000Z"
                }
              ],
              "created_at": "2026-08-30T12:00:01.000000Z",
              "updated_at": "2026-08-30T12:00:01.000000Z"
            }
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "description",
        "visibility",
        "is_draft",
        "delivery_text",
        "category",
        "level",
        "language",
        "subtitle",
        "author",
        "subcategory",
        "what_you_learn",
        "requirements",
        "certificate_enabled",
        "access_type",
        "access_duration_days",
        "enrollment_limit",
        "promo_video",
        "sections",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 0,
    "title": "string",
    "slug": "string",
    "description": "string",
    "visibility": "PUBLIC",
    "is_draft": true,
    "delivery_text": "string",
    "category": "development",
    "level": "all_levels",
    "language": "string",
    "subtitle": "string",
    "author": "string",
    "subcategory": "string",
    "what_you_learn": [
      "string"
    ],
    "requirements": [
      "string"
    ],
    "certificate_enabled": true,
    "access_type": "lifetime",
    "access_duration_days": 1,
    "enrollment_limit": 1,
    "promo_video": {
      "mux_playback_id": "string",
      "mux_status": "string",
      "duration_seconds": 0
    },
    "sections": [
      {
        "id": 1,
        "title": "Getting started",
        "description": null,
        "sort_order": 1,
        "lessons": [
          {
            "id": 1,
            "section_id": 1,
            "title": "Welcome to the reading room",
            "content": "Read the first founder memo.",
            "type": "lecture",
            "is_preview": false,
            "is_published": false,
            "sort_order": 1,
            "video": null,
            "attachments": [],
            "assignment": null,
            "questions": [],
            "created_at": "2026-08-30T12:00:01.000000Z",
            "updated_at": "2026-08-30T12:00:01.000000Z"
          }
        ],
        "created_at": "2026-08-30T12:00:01.000000Z",
        "updated_at": "2026-08-30T12:00:01.000000Z"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "updated_at": "2019-08-24T14:15:22Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Reorder course sections (/docs/api/courses/reorder-course-sections)

Send every section ID exactly once in the desired order. Missing, duplicate, or foreign IDs return `422` without partially changing positions.

## PATCH /v2/courses/{course}/sections/reorder

Reorder course sections

Replace the complete section order. Send every section ID exactly once in the desired order. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.coursesSections.reorder({
  "course": "string_example",
  "resources": [501, 502]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses_sections.reorder(
    course="string_example",
    resources=[501, 502]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->coursesSections()->reorder(
    course: 'string_example',
    resources: [501, 502],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CoursesSectionsReorderParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[501,502]}"), params); err != nil { panic(err) }
    result, err := client.CoursesSections().Reorder(context.Background(), "string_example", params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CoursesSections.ReorderAsync(
    "string_example",
    new CoursesSectionsReorderOptions
    {
        Resources = JsonConvert.DeserializeObject<List<long>>("[501,502]")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.coursesSections.reorder(course = "string_example", resources = listOf(501L, 502L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses_sections.reorder(
  course: "string_example",
  resources: [501, 502]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses_sections::ReorderParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReorderParams::new(serde_json::from_str("{\"resources\":[501,502]}")?);
    let result = client.courses_sections().reorder("string_example", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CoursesSections.reorder(client, "string_example", %{"resources" => [501, 502]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses sections reorder test_course --body '{"resources":[501,502]}' --yes

```

- Method: `PATCH`

- Path: `/v2/courses/{course}/sections/reorder`

- Full URL: `https://sell.app/api/v2/courses/{course}/sections/reorder`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COURSE_ID='replace-me'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/${SELLAPP_COURSE_ID}/sections/reorder" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    501,
    502
  ]
}'
```

## Path Parameters
- `course` (`string`, required): The course path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "integer",
        "minimum": 1
      },
      "uniqueItems": true
    }
  },
  "required": [
    "resources"
  ]
}
```

Example (minimal):

```json
{
  "resources": [
    501,
    502
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ]
        },
        "is_draft": {
          "type": "boolean"
        },
        "delivery_text": {
          "type": [
            "string",
            "null"
          ]
        },
        "category": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "development",
            "business",
            "marketing",
            "design",
            "finance",
            "it-software",
            "personal-development",
            "productivity",
            "other",
            null
          ]
        },
        "level": {
          "type": "string",
          "enum": [
            "all_levels",
            "beginner",
            "intermediate",
            "advanced"
          ]
        },
        "language": {
          "type": "string"
        },
        "subtitle": {
          "type": [
            "string",
            "null"
          ]
        },
        "author": {
          "type": [
            "string",
            "null"
          ]
        },
        "subcategory": {
          "type": [
            "string",
            "null"
          ]
        },
        "what_you_learn": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "requirements": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "certificate_enabled": {
          "type": "boolean"
        },
        "access_type": {
          "type": "string",
          "enum": [
            "lifetime",
            "limited"
          ]
        },
        "access_duration_days": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1,
          "maximum": 3650
        },
        "enrollment_limit": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1
        },
        "promo_video": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "mux_playback_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "mux_status": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "duration_seconds": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                }
              },
              "required": [
                "mux_playback_id",
                "mux_status",
                "duration_seconds"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "sections": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              },
              "lessons": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "section_id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "content": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "lecture",
                        "video",
                        "text",
                        "quiz",
                        "assignment"
                      ]
                    },
                    "is_preview": {
                      "type": "boolean"
                    },
                    "is_published": {
                      "type": "boolean"
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "video": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "source": {
                              "type": "string",
                              "enum": [
                                "mux",
                                "external"
                              ]
                            },
                            "external_url": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "format": "uri"
                            },
                            "mux_playback_id": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "mux_status": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "duration_seconds": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 0
                            }
                          },
                          "required": [
                            "source",
                            "external_url",
                            "mux_playback_id",
                            "mux_status",
                            "duration_seconds"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attachments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "title": {
                            "type": "string"
                          },
                          "mime_type": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "size_bytes": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "minimum": 0
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          }
                        },
                        "required": [
                          "id",
                          "title",
                          "mime_type",
                          "size_bytes",
                          "sort_order"
                        ]
                      }
                    },
                    "assignment": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "estimated_duration_minutes": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 1,
                              "maximum": 1440
                            },
                            "instructions": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "questions": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "integer"
                                  },
                                  "prompt": {
                                    "type": "string"
                                  },
                                  "question_type": {
                                    "type": "string",
                                    "enum": [
                                      "text",
                                      "single_choice",
                                      "multiple_choice"
                                    ]
                                  },
                                  "solution": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "sort_order": {
                                    "type": "integer",
                                    "minimum": 1
                                  },
                                  "answers": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "id": {
                                          "type": "integer"
                                        },
                                        "answer": {
                                          "type": "string"
                                        },
                                        "is_correct": {
                                          "type": "boolean"
                                        },
                                        "sort_order": {
                                          "type": "integer",
                                          "minimum": 1
                                        }
                                      },
                                      "required": [
                                        "id",
                                        "answer",
                                        "is_correct",
                                        "sort_order"
                                      ]
                                    }
                                  },
                                  "created_at": {
                                    "type": "string",
                                    "format": "date-time"
                                  },
                                  "updated_at": {
                                    "type": "string",
                                    "format": "date-time"
                                  }
                                },
                                "required": [
                                  "id",
                                  "prompt",
                                  "question_type",
                                  "solution",
                                  "sort_order",
                                  "answers",
                                  "created_at",
                                  "updated_at"
                                ]
                              }
                            }
                          },
                          "required": [
                            "estimated_duration_minutes",
                            "instructions",
                            "questions"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "questions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "prompt": {
                            "type": "string"
                          },
                          "question_type": {
                            "type": "string",
                            "enum": [
                              "text",
                              "single_choice",
                              "multiple_choice"
                            ]
                          },
                          "solution": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "answers": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "answer": {
                                  "type": "string"
                                },
                                "is_correct": {
                                  "type": "boolean"
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                }
                              },
                              "required": [
                                "id",
                                "answer",
                                "is_correct",
                                "sort_order"
                              ]
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "prompt",
                          "question_type",
                          "solution",
                          "sort_order",
                          "answers",
                          "created_at",
                          "updated_at"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "section_id",
                    "title",
                    "content",
                    "type",
                    "is_preview",
                    "is_published",
                    "sort_order",
                    "video",
                    "attachments",
                    "assignment",
                    "questions",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "title",
              "description",
              "sort_order",
              "lessons",
              "created_at",
              "updated_at"
            ]
          },
          "example": [
            {
              "id": 1,
              "title": "Getting started",
              "description": null,
              "sort_order": 1,
              "lessons": [
                {
                  "id": 1,
                  "section_id": 1,
                  "title": "Welcome to the reading room",
                  "content": "Read the first founder memo.",
                  "type": "lecture",
                  "is_preview": false,
                  "is_published": false,
                  "sort_order": 1,
                  "video": null,
                  "attachments": [],
                  "assignment": null,
                  "questions": [],
                  "created_at": "2026-08-30T12:00:01.000000Z",
                  "updated_at": "2026-08-30T12:00:01.000000Z"
                }
              ],
              "created_at": "2026-08-30T12:00:01.000000Z",
              "updated_at": "2026-08-30T12:00:01.000000Z"
            }
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "description",
        "visibility",
        "is_draft",
        "delivery_text",
        "category",
        "level",
        "language",
        "subtitle",
        "author",
        "subcategory",
        "what_you_learn",
        "requirements",
        "certificate_enabled",
        "access_type",
        "access_duration_days",
        "enrollment_limit",
        "promo_video",
        "sections",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 0,
    "title": "string",
    "slug": "string",
    "description": "string",
    "visibility": "PUBLIC",
    "is_draft": true,
    "delivery_text": "string",
    "category": "development",
    "level": "all_levels",
    "language": "string",
    "subtitle": "string",
    "author": "string",
    "subcategory": "string",
    "what_you_learn": [
      "string"
    ],
    "requirements": [
      "string"
    ],
    "certificate_enabled": true,
    "access_type": "lifetime",
    "access_duration_days": 1,
    "enrollment_limit": 1,
    "promo_video": {
      "mux_playback_id": "string",
      "mux_status": "string",
      "duration_seconds": 0
    },
    "sections": [
      {
        "id": 1,
        "title": "Getting started",
        "description": null,
        "sort_order": 1,
        "lessons": [
          {
            "id": 1,
            "section_id": 1,
            "title": "Welcome to the reading room",
            "content": "Read the first founder memo.",
            "type": "lecture",
            "is_preview": false,
            "is_published": false,
            "sort_order": 1,
            "video": null,
            "attachments": [],
            "assignment": null,
            "questions": [],
            "created_at": "2026-08-30T12:00:01.000000Z",
            "updated_at": "2026-08-30T12:00:01.000000Z"
          }
        ],
        "created_at": "2026-08-30T12:00:01.000000Z",
        "updated_at": "2026-08-30T12:00:01.000000Z"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "updated_at": "2019-08-24T14:15:22Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve a course (/docs/api/courses/retrieve-course)

The response includes course access configuration, promotional video references, ordered sections, lesson content, attachment metadata, assignments, quizzes, questions, and answers.

## GET /v2/courses/{course}

Retrieve a course

Retrieve one store-scoped course by listing ID or slug with its ordered curriculum. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.courses.get({
  "course": "string_example"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses.get(course="string_example")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->courses()->get(course: 'string_example');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Courses().Get(context.Background(), "string_example")
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Courses.GetAsync("string_example");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.courses.get(course = "string_example")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses.get(course: "string_example")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.courses().get("string_example", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Courses.get(client, "string_example")
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses get test_course

```

- Method: `GET`

- Path: `/v2/courses/{course}`

- Full URL: `https://sell.app/api/v2/courses/{course}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COURSE_ID='replace-me'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/${SELLAPP_COURSE_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `course` (`string`, required): The course path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ]
        },
        "is_draft": {
          "type": "boolean"
        },
        "delivery_text": {
          "type": [
            "string",
            "null"
          ]
        },
        "category": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "development",
            "business",
            "marketing",
            "design",
            "finance",
            "it-software",
            "personal-development",
            "productivity",
            "other",
            null
          ]
        },
        "level": {
          "type": "string",
          "enum": [
            "all_levels",
            "beginner",
            "intermediate",
            "advanced"
          ]
        },
        "language": {
          "type": "string"
        },
        "subtitle": {
          "type": [
            "string",
            "null"
          ]
        },
        "author": {
          "type": [
            "string",
            "null"
          ]
        },
        "subcategory": {
          "type": [
            "string",
            "null"
          ]
        },
        "what_you_learn": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "requirements": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "certificate_enabled": {
          "type": "boolean"
        },
        "access_type": {
          "type": "string",
          "enum": [
            "lifetime",
            "limited"
          ]
        },
        "access_duration_days": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1,
          "maximum": 3650
        },
        "enrollment_limit": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1
        },
        "promo_video": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "mux_playback_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "mux_status": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "duration_seconds": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                }
              },
              "required": [
                "mux_playback_id",
                "mux_status",
                "duration_seconds"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "sections": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              },
              "lessons": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "section_id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "content": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "lecture",
                        "video",
                        "text",
                        "quiz",
                        "assignment"
                      ]
                    },
                    "is_preview": {
                      "type": "boolean"
                    },
                    "is_published": {
                      "type": "boolean"
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "video": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "source": {
                              "type": "string",
                              "enum": [
                                "mux",
                                "external"
                              ]
                            },
                            "external_url": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "format": "uri"
                            },
                            "mux_playback_id": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "mux_status": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "duration_seconds": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 0
                            }
                          },
                          "required": [
                            "source",
                            "external_url",
                            "mux_playback_id",
                            "mux_status",
                            "duration_seconds"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attachments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "title": {
                            "type": "string"
                          },
                          "mime_type": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "size_bytes": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "minimum": 0
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          }
                        },
                        "required": [
                          "id",
                          "title",
                          "mime_type",
                          "size_bytes",
                          "sort_order"
                        ]
                      }
                    },
                    "assignment": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "estimated_duration_minutes": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 1,
                              "maximum": 1440
                            },
                            "instructions": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "questions": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "integer"
                                  },
                                  "prompt": {
                                    "type": "string"
                                  },
                                  "question_type": {
                                    "type": "string",
                                    "enum": [
                                      "text",
                                      "single_choice",
                                      "multiple_choice"
                                    ]
                                  },
                                  "solution": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "sort_order": {
                                    "type": "integer",
                                    "minimum": 1
                                  },
                                  "answers": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "id": {
                                          "type": "integer"
                                        },
                                        "answer": {
                                          "type": "string"
                                        },
                                        "is_correct": {
                                          "type": "boolean"
                                        },
                                        "sort_order": {
                                          "type": "integer",
                                          "minimum": 1
                                        }
                                      },
                                      "required": [
                                        "id",
                                        "answer",
                                        "is_correct",
                                        "sort_order"
                                      ]
                                    }
                                  },
                                  "created_at": {
                                    "type": "string",
                                    "format": "date-time"
                                  },
                                  "updated_at": {
                                    "type": "string",
                                    "format": "date-time"
                                  }
                                },
                                "required": [
                                  "id",
                                  "prompt",
                                  "question_type",
                                  "solution",
                                  "sort_order",
                                  "answers",
                                  "created_at",
                                  "updated_at"
                                ]
                              }
                            }
                          },
                          "required": [
                            "estimated_duration_minutes",
                            "instructions",
                            "questions"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "questions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "prompt": {
                            "type": "string"
                          },
                          "question_type": {
                            "type": "string",
                            "enum": [
                              "text",
                              "single_choice",
                              "multiple_choice"
                            ]
                          },
                          "solution": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "answers": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "answer": {
                                  "type": "string"
                                },
                                "is_correct": {
                                  "type": "boolean"
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                }
                              },
                              "required": [
                                "id",
                                "answer",
                                "is_correct",
                                "sort_order"
                              ]
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "prompt",
                          "question_type",
                          "solution",
                          "sort_order",
                          "answers",
                          "created_at",
                          "updated_at"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "section_id",
                    "title",
                    "content",
                    "type",
                    "is_preview",
                    "is_published",
                    "sort_order",
                    "video",
                    "attachments",
                    "assignment",
                    "questions",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "title",
              "description",
              "sort_order",
              "lessons",
              "created_at",
              "updated_at"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "description",
        "visibility",
        "is_draft",
        "delivery_text",
        "category",
        "level",
        "language",
        "subtitle",
        "author",
        "subcategory",
        "what_you_learn",
        "requirements",
        "certificate_enabled",
        "access_type",
        "access_duration_days",
        "enrollment_limit",
        "promo_video",
        "sections",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 50,
    "title": "Design foundations",
    "slug": "design-foundations",
    "description": "Build your first design with reusable templates.",
    "visibility": "HIDDEN",
    "is_draft": false,
    "delivery_text": "Open your course to get started.",
    "category": "design",
    "level": "all_levels",
    "language": "en",
    "subtitle": null,
    "author": "Launch Lab",
    "subcategory": null,
    "what_you_learn": [
      "Customize a reusable template."
    ],
    "requirements": [
      "A web browser."
    ],
    "certificate_enabled": false,
    "access_type": "lifetime",
    "access_duration_days": null,
    "enrollment_limit": null,
    "promo_video": null,
    "sections": [
      {
        "id": 51,
        "title": "Getting started",
        "description": "Your first project.",
        "sort_order": 1,
        "lessons": [
          {
            "id": 52,
            "section_id": 51,
            "title": "Build your first design",
            "content": "Choose a template and add your project details.",
            "type": "lecture",
            "is_preview": false,
            "is_published": false,
            "sort_order": 1,
            "video": null,
            "attachments": [],
            "assignment": null,
            "questions": [],
            "created_at": "2026-09-01T12:00:00Z",
            "updated_at": "2026-09-01T12:00:00Z"
          }
        ],
        "created_at": "2026-09-01T12:00:00Z",
        "updated_at": "2026-09-01T12:00:00Z"
      }
    ],
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Search courses (/docs/api/courses/search-courses)

Supported filters are `id`, `title`, `slug`, `visibility`, and `is_draft`. Supported sort fields are `id`, `title`, `slug`, `visibility`, `is_draft`, `created_at`, and `updated_at`.

## POST /v2/courses/search

Search courses

Search courses by title, slug, or description and compose supported filters and sort instructions. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.courses.search({
  "filters": [{"field": "id", "operator": "=", "value": 1}],
  "sort": [{"field": "created_at", "direction": "desc"}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses.search(
    filters=[{"field": "id", "operator": "=", "value": 1}],
    sort=[{"field": "created_at", "direction": "desc"}]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->courses()->search(
    filters: [['field' => 'id', 'operator' => '=', 'value' => 1]],
    sort: [['field' => 'created_at', 'direction' => 'desc']],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CoursesSearchParams{}
    if err := json.Unmarshal([]byte("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}"), params); err != nil { panic(err) }
    page := client.Courses().Search(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Courses.SearchAsync(new CoursesSearchOptions
    {
        Filters = JsonConvert.DeserializeObject<List<SearchRewardRulesRequestApplicationJsonPropertyFiltersItem>>("[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}]")!,
        Sort = JsonConvert.DeserializeObject<List<SearchRewardRulesRequestApplicationJsonPropertySortItem>>("[{\"field\":\"created_at\",\"direction\":\"desc\"}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.courses.search(filters = listOf(ObjectMapperFactory.read("{\"field\":\"id\",\"operator\":\"=\",\"value\":1}", app.sell.sellapp.models.SearchRewardRulesRequestApplicationJsonPropertyFiltersItem::class.java)), sort = listOf(ObjectMapperFactory.read("{\"field\":\"created_at\",\"direction\":\"desc\"}", app.sell.sellapp.models.SearchRewardRulesRequestApplicationJsonPropertySortItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses.search(
  filters: [{ field: "id", operator: "=", value: 1 }],
  sort: [{ field: "created_at", direction: "desc" }]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses::SearchParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = SearchParams::new(serde_json::from_str("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}")?);
    let result = client.courses().search(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Courses.search(client, %{"filters" => [%{"field" => "id", "operator" => "=", "value" => 1}], "sort" => [%{"field" => "created_at", "direction" => "desc"}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses search --body '{"filters":[{"field":"id","operator":"=","value":1}],"sort":[{"field":"created_at","direction":"desc"}]}'

```

- Method: `POST`

- Path: `/v2/courses/search`

- Full URL: `https://sell.app/api/v2/courses/search`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching items in one data array without pagination links or metadata.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "operator": {
            "type": "string",
            "default": "="
          },
          "value": {},
          "type": {
            "type": "string",
            "enum": [
              "and",
              "or"
            ],
            "default": "and"
          },
          "nested": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "anyOf": [
          {
            "required": [
              "field"
            ]
          },
          {
            "required": [
              "nested"
            ]
          }
        ]
      }
    },
    "sort": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "default": "asc"
          }
        },
        "required": [
          "field"
        ]
      }
    },
    "search": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "null"
          ]
        },
        "case_sensitive": {
          "type": "boolean"
        }
      }
    },
    "includes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "relation": {
            "type": "string"
          }
        },
        "required": [
          "relation"
        ]
      }
    }
  }
}
```

Example:

```json
{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer",
                "example": 1
              },
              "title": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ]
              },
              "is_draft": {
                "type": "boolean"
              },
              "delivery_text": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "category": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "development",
                  "business",
                  "marketing",
                  "design",
                  "finance",
                  "it-software",
                  "personal-development",
                  "productivity",
                  "other",
                  null
                ]
              },
              "level": {
                "type": "string",
                "enum": [
                  "all_levels",
                  "beginner",
                  "intermediate",
                  "advanced"
                ]
              },
              "language": {
                "type": "string"
              },
              "subtitle": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "author": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "subcategory": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "what_you_learn": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "requirements": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "certificate_enabled": {
                "type": "boolean"
              },
              "access_type": {
                "type": "string",
                "enum": [
                  "lifetime",
                  "limited"
                ]
              },
              "access_duration_days": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 1,
                "maximum": 3650
              },
              "enrollment_limit": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 1
              },
              "promo_video": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "mux_playback_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "mux_status": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "duration_seconds": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 0
                      }
                    },
                    "required": [
                      "mux_playback_id",
                      "mux_status",
                      "duration_seconds"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "sections": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "lessons": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "section_id": {
                            "type": "integer"
                          },
                          "title": {
                            "type": "string"
                          },
                          "content": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "lecture",
                              "video",
                              "text",
                              "quiz",
                              "assignment"
                            ]
                          },
                          "is_preview": {
                            "type": "boolean"
                          },
                          "is_published": {
                            "type": "boolean"
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "video": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "source": {
                                    "type": "string",
                                    "enum": [
                                      "mux",
                                      "external"
                                    ]
                                  },
                                  "external_url": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "format": "uri"
                                  },
                                  "mux_playback_id": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "mux_status": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "duration_seconds": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ],
                                    "minimum": 0
                                  }
                                },
                                "required": [
                                  "source",
                                  "external_url",
                                  "mux_playback_id",
                                  "mux_status",
                                  "duration_seconds"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "attachments": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "title": {
                                  "type": "string"
                                },
                                "mime_type": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "size_bytes": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ],
                                  "minimum": 0
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                }
                              },
                              "required": [
                                "id",
                                "title",
                                "mime_type",
                                "size_bytes",
                                "sort_order"
                              ]
                            }
                          },
                          "assignment": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "estimated_duration_minutes": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ],
                                    "minimum": 1,
                                    "maximum": 1440
                                  },
                                  "instructions": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "questions": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "id": {
                                          "type": "integer"
                                        },
                                        "prompt": {
                                          "type": "string"
                                        },
                                        "question_type": {
                                          "type": "string",
                                          "enum": [
                                            "text",
                                            "single_choice",
                                            "multiple_choice"
                                          ]
                                        },
                                        "solution": {
                                          "type": [
                                            "string",
                                            "null"
                                          ]
                                        },
                                        "sort_order": {
                                          "type": "integer",
                                          "minimum": 1
                                        },
                                        "answers": {
                                          "type": "array",
                                          "items": {
                                            "type": "object",
                                            "properties": {
                                              "id": {
                                                "type": "integer"
                                              },
                                              "answer": {
                                                "type": "string"
                                              },
                                              "is_correct": {
                                                "type": "boolean"
                                              },
                                              "sort_order": {
                                                "type": "integer",
                                                "minimum": 1
                                              }
                                            },
                                            "required": [
                                              "id",
                                              "answer",
                                              "is_correct",
                                              "sort_order"
                                            ]
                                          }
                                        },
                                        "created_at": {
                                          "type": "string",
                                          "format": "date-time"
                                        },
                                        "updated_at": {
                                          "type": "string",
                                          "format": "date-time"
                                        }
                                      },
                                      "required": [
                                        "id",
                                        "prompt",
                                        "question_type",
                                        "solution",
                                        "sort_order",
                                        "answers",
                                        "created_at",
                                        "updated_at"
                                      ]
                                    }
                                  }
                                },
                                "required": [
                                  "estimated_duration_minutes",
                                  "instructions",
                                  "questions"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "questions": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "prompt": {
                                  "type": "string"
                                },
                                "question_type": {
                                  "type": "string",
                                  "enum": [
                                    "text",
                                    "single_choice",
                                    "multiple_choice"
                                  ]
                                },
                                "solution": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                },
                                "answers": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "id": {
                                        "type": "integer"
                                      },
                                      "answer": {
                                        "type": "string"
                                      },
                                      "is_correct": {
                                        "type": "boolean"
                                      },
                                      "sort_order": {
                                        "type": "integer",
                                        "minimum": 1
                                      }
                                    },
                                    "required": [
                                      "id",
                                      "answer",
                                      "is_correct",
                                      "sort_order"
                                    ]
                                  }
                                },
                                "created_at": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "updated_at": {
                                  "type": "string",
                                  "format": "date-time"
                                }
                              },
                              "required": [
                                "id",
                                "prompt",
                                "question_type",
                                "solution",
                                "sort_order",
                                "answers",
                                "created_at",
                                "updated_at"
                              ]
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "section_id",
                          "title",
                          "content",
                          "type",
                          "is_preview",
                          "is_published",
                          "sort_order",
                          "video",
                          "attachments",
                          "assignment",
                          "questions",
                          "created_at",
                          "updated_at"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "description",
                    "sort_order",
                    "lessons",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "title",
              "slug",
              "description",
              "visibility",
              "is_draft",
              "delivery_text",
              "category",
              "level",
              "language",
              "subtitle",
              "author",
              "subcategory",
              "what_you_learn",
              "requirements",
              "certificate_enabled",
              "access_type",
              "access_duration_days",
              "enrollment_limit",
              "promo_video",
              "sections",
              "created_at",
              "updated_at"
            ]
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer",
                "example": 1
              },
              "title": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ]
              },
              "is_draft": {
                "type": "boolean"
              },
              "delivery_text": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "category": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "development",
                  "business",
                  "marketing",
                  "design",
                  "finance",
                  "it-software",
                  "personal-development",
                  "productivity",
                  "other",
                  null
                ]
              },
              "level": {
                "type": "string",
                "enum": [
                  "all_levels",
                  "beginner",
                  "intermediate",
                  "advanced"
                ]
              },
              "language": {
                "type": "string"
              },
              "subtitle": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "author": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "subcategory": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "what_you_learn": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "requirements": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "certificate_enabled": {
                "type": "boolean"
              },
              "access_type": {
                "type": "string",
                "enum": [
                  "lifetime",
                  "limited"
                ]
              },
              "access_duration_days": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 1,
                "maximum": 3650
              },
              "enrollment_limit": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 1
              },
              "promo_video": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "mux_playback_id": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "mux_status": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "duration_seconds": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 0
                      }
                    },
                    "required": [
                      "mux_playback_id",
                      "mux_status",
                      "duration_seconds"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "sections": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "lessons": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "section_id": {
                            "type": "integer"
                          },
                          "title": {
                            "type": "string"
                          },
                          "content": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "lecture",
                              "video",
                              "text",
                              "quiz",
                              "assignment"
                            ]
                          },
                          "is_preview": {
                            "type": "boolean"
                          },
                          "is_published": {
                            "type": "boolean"
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "video": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "source": {
                                    "type": "string",
                                    "enum": [
                                      "mux",
                                      "external"
                                    ]
                                  },
                                  "external_url": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "format": "uri"
                                  },
                                  "mux_playback_id": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "mux_status": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "duration_seconds": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ],
                                    "minimum": 0
                                  }
                                },
                                "required": [
                                  "source",
                                  "external_url",
                                  "mux_playback_id",
                                  "mux_status",
                                  "duration_seconds"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "attachments": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "title": {
                                  "type": "string"
                                },
                                "mime_type": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "size_bytes": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ],
                                  "minimum": 0
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                }
                              },
                              "required": [
                                "id",
                                "title",
                                "mime_type",
                                "size_bytes",
                                "sort_order"
                              ]
                            }
                          },
                          "assignment": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "estimated_duration_minutes": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ],
                                    "minimum": 1,
                                    "maximum": 1440
                                  },
                                  "instructions": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "questions": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "id": {
                                          "type": "integer"
                                        },
                                        "prompt": {
                                          "type": "string"
                                        },
                                        "question_type": {
                                          "type": "string",
                                          "enum": [
                                            "text",
                                            "single_choice",
                                            "multiple_choice"
                                          ]
                                        },
                                        "solution": {
                                          "type": [
                                            "string",
                                            "null"
                                          ]
                                        },
                                        "sort_order": {
                                          "type": "integer",
                                          "minimum": 1
                                        },
                                        "answers": {
                                          "type": "array",
                                          "items": {
                                            "type": "object",
                                            "properties": {
                                              "id": {
                                                "type": "integer"
                                              },
                                              "answer": {
                                                "type": "string"
                                              },
                                              "is_correct": {
                                                "type": "boolean"
                                              },
                                              "sort_order": {
                                                "type": "integer",
                                                "minimum": 1
                                              }
                                            },
                                            "required": [
                                              "id",
                                              "answer",
                                              "is_correct",
                                              "sort_order"
                                            ]
                                          }
                                        },
                                        "created_at": {
                                          "type": "string",
                                          "format": "date-time"
                                        },
                                        "updated_at": {
                                          "type": "string",
                                          "format": "date-time"
                                        }
                                      },
                                      "required": [
                                        "id",
                                        "prompt",
                                        "question_type",
                                        "solution",
                                        "sort_order",
                                        "answers",
                                        "created_at",
                                        "updated_at"
                                      ]
                                    }
                                  }
                                },
                                "required": [
                                  "estimated_duration_minutes",
                                  "instructions",
                                  "questions"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "questions": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "prompt": {
                                  "type": "string"
                                },
                                "question_type": {
                                  "type": "string",
                                  "enum": [
                                    "text",
                                    "single_choice",
                                    "multiple_choice"
                                  ]
                                },
                                "solution": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                },
                                "answers": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "id": {
                                        "type": "integer"
                                      },
                                      "answer": {
                                        "type": "string"
                                      },
                                      "is_correct": {
                                        "type": "boolean"
                                      },
                                      "sort_order": {
                                        "type": "integer",
                                        "minimum": 1
                                      }
                                    },
                                    "required": [
                                      "id",
                                      "answer",
                                      "is_correct",
                                      "sort_order"
                                    ]
                                  }
                                },
                                "created_at": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "updated_at": {
                                  "type": "string",
                                  "format": "date-time"
                                }
                              },
                              "required": [
                                "id",
                                "prompt",
                                "question_type",
                                "solution",
                                "sort_order",
                                "answers",
                                "created_at",
                                "updated_at"
                              ]
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "section_id",
                          "title",
                          "content",
                          "type",
                          "is_preview",
                          "is_published",
                          "sort_order",
                          "video",
                          "attachments",
                          "assignment",
                          "questions",
                          "created_at",
                          "updated_at"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "title",
                    "description",
                    "sort_order",
                    "lessons",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "title",
              "slug",
              "description",
              "visibility",
              "is_draft",
              "delivery_text",
              "category",
              "level",
              "language",
              "subtitle",
              "author",
              "subcategory",
              "what_you_learn",
              "requirements",
              "certificate_enabled",
              "access_type",
              "access_duration_days",
              "enrollment_limit",
              "promo_video",
              "sections",
              "created_at",
              "updated_at"
            ]
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example (minimal):

```json
{
  "data": [
    {
      "id": 1,
      "title": "Design foundations",
      "slug": "design-foundations",
      "description": "Build your first design with reusable templates.",
      "visibility": "HIDDEN",
      "is_draft": false,
      "delivery_text": "Open your course to get started.",
      "category": "design",
      "level": "all_levels",
      "language": "en",
      "subtitle": null,
      "author": "Launch Lab",
      "subcategory": null,
      "what_you_learn": [
        "Customize a reusable template."
      ],
      "requirements": [
        "A web browser."
      ],
      "certificate_enabled": false,
      "access_type": "lifetime",
      "access_duration_days": null,
      "enrollment_limit": null,
      "promo_video": null,
      "sections": [
        {
          "id": 51,
          "title": "Getting started",
          "description": "Your first project.",
          "sort_order": 1,
          "lessons": [
            {
              "id": 52,
              "section_id": 51,
              "title": "Build your first design",
              "content": "Choose a template and add your project details.",
              "type": "lecture",
              "is_preview": false,
              "is_published": false,
              "sort_order": 1,
              "video": null,
              "attachments": [],
              "assignment": null,
              "questions": [],
              "created_at": "2026-09-01T12:00:00Z",
              "updated_at": "2026-09-01T12:00:00Z"
            }
          ],
          "created_at": "2026-09-01T12:00:00Z",
          "updated_at": "2026-09-01T12:00:00Z"
        }
      ],
      "created_at": "2026-09-01T12:00:00Z",
      "updated_at": "2026-09-01T12:00:00Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/courses/search?page=1",
    "last": "https://sell.app/api/v2/courses/search?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/courses/search?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ],
    "path": "https://sell.app/api/v2/courses/search",
    "per_page": 15,
    "to": 1,
    "total": 1
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Update a course (/docs/api/courses/update-course)

Use `access_type: "limited"` with `access_duration_days` to configure time-limited customer access. Switching to `lifetime` clears the duration. `enrollment_limit` is optional.

Before changing `visibility` to `PUBLIC`, SellApp checks that the course has a ready promotional video and at least one published lesson. If either is missing, the change is rejected.

## PATCH /v2/courses/{course}

Update a course

Update course metadata, access configuration, delivery copy, or publication visibility. Public visibility requires a ready promotional video and at least one published lesson. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.courses.update({
  "course": "string_example",
  "level": "beginner",
  "visibility": "HIDDEN"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses.update(
    course="string_example",
    level="beginner",
    visibility="HIDDEN"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->courses()->update(
    course: 'string_example',
    level: 'beginner',
    visibility: 'HIDDEN',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CoursesUpdateParams{}
    if err := json.Unmarshal([]byte("{\"level\":\"beginner\",\"visibility\":\"HIDDEN\"}"), params); err != nil { panic(err) }
    result, err := client.Courses().Update(context.Background(), "string_example", params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Courses.UpdateAsync(
    "string_example",
    new CoursesUpdateOptions
    {
        Level = JsonConvert.DeserializeObject<SdkUpdateCourseRequestApplicationJsonLevel>("\"beginner\"")!,
        Visibility = JsonConvert.DeserializeObject<CatalogVisibility>("\"HIDDEN\"")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.courses.update(course = "string_example", level = app.sell.sellapp.common.http.PatchField.Present(app.sell.sellapp.types.SdkUpdateCourseRequestApplicationJsonLevel("beginner")), visibility = app.sell.sellapp.common.http.PatchField.Present(app.sell.sellapp.types.CatalogVisibility("HIDDEN")))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses.update(
  course: "string_example",
  level: "beginner",
  visibility: "HIDDEN"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{\"level\":\"beginner\",\"visibility\":\"HIDDEN\"}")?);
    let result = client.courses().update("string_example", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Courses.update(client, "string_example", %{"level" => "beginner", "visibility" => "HIDDEN"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses update test_course --level beginner --visibility HIDDEN

```

- Method: `PATCH`

- Path: `/v2/courses/{course}`

- Full URL: `https://sell.app/api/v2/courses/{course}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COURSE_ID='replace-me'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/${SELLAPP_COURSE_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "level": "beginner",
  "visibility": "HIDDEN"
}'
```

## Path Parameters
- `course` (`string`, required): The course path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "category": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "development",
        "business",
        "marketing",
        "design",
        "finance",
        "it-software",
        "personal-development",
        "productivity",
        "other",
        null
      ]
    },
    "level": {
      "type": "string",
      "enum": [
        "all_levels",
        "beginner",
        "intermediate",
        "advanced"
      ]
    },
    "language": {
      "type": "string",
      "maxLength": 255
    },
    "subtitle": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 120
    },
    "author": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 120
    },
    "subcategory": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 255
    },
    "what_you_learn": {
      "type": "array",
      "maxItems": 50,
      "items": {
        "type": "string",
        "maxLength": 255
      }
    },
    "requirements": {
      "type": "array",
      "maxItems": 50,
      "items": {
        "type": "string",
        "maxLength": 255
      }
    },
    "certificate_enabled": {
      "type": "boolean"
    },
    "access_type": {
      "type": "string",
      "enum": [
        "lifetime",
        "limited"
      ]
    },
    "access_duration_days": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1,
      "maximum": 3650,
      "description": "Required when access_type is limited; cleared otherwise."
    },
    "enrollment_limit": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "delivery_text": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 65535
    },
    "visibility": {
      "type": "string",
      "enum": [
        "PUBLIC",
        "ON_HOLD",
        "HIDDEN",
        "PRIVATE"
      ]
    },
    "expected_updated_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
```

Example (minimal):

```json
{
  "level": "beginner",
  "visibility": "HIDDEN"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ]
        },
        "is_draft": {
          "type": "boolean"
        },
        "delivery_text": {
          "type": [
            "string",
            "null"
          ]
        },
        "category": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "development",
            "business",
            "marketing",
            "design",
            "finance",
            "it-software",
            "personal-development",
            "productivity",
            "other",
            null
          ]
        },
        "level": {
          "type": "string",
          "enum": [
            "all_levels",
            "beginner",
            "intermediate",
            "advanced"
          ]
        },
        "language": {
          "type": "string"
        },
        "subtitle": {
          "type": [
            "string",
            "null"
          ]
        },
        "author": {
          "type": [
            "string",
            "null"
          ]
        },
        "subcategory": {
          "type": [
            "string",
            "null"
          ]
        },
        "what_you_learn": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "requirements": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "certificate_enabled": {
          "type": "boolean"
        },
        "access_type": {
          "type": "string",
          "enum": [
            "lifetime",
            "limited"
          ]
        },
        "access_duration_days": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1,
          "maximum": 3650
        },
        "enrollment_limit": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1
        },
        "promo_video": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "mux_playback_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "mux_status": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "duration_seconds": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                }
              },
              "required": [
                "mux_playback_id",
                "mux_status",
                "duration_seconds"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "sections": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              },
              "lessons": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "section_id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "content": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "lecture",
                        "video",
                        "text",
                        "quiz",
                        "assignment"
                      ]
                    },
                    "is_preview": {
                      "type": "boolean"
                    },
                    "is_published": {
                      "type": "boolean"
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "video": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "source": {
                              "type": "string",
                              "enum": [
                                "mux",
                                "external"
                              ]
                            },
                            "external_url": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "format": "uri"
                            },
                            "mux_playback_id": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "mux_status": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "duration_seconds": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 0
                            }
                          },
                          "required": [
                            "source",
                            "external_url",
                            "mux_playback_id",
                            "mux_status",
                            "duration_seconds"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attachments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "title": {
                            "type": "string"
                          },
                          "mime_type": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "size_bytes": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "minimum": 0
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          }
                        },
                        "required": [
                          "id",
                          "title",
                          "mime_type",
                          "size_bytes",
                          "sort_order"
                        ]
                      }
                    },
                    "assignment": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "estimated_duration_minutes": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 1,
                              "maximum": 1440
                            },
                            "instructions": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "questions": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "integer"
                                  },
                                  "prompt": {
                                    "type": "string"
                                  },
                                  "question_type": {
                                    "type": "string",
                                    "enum": [
                                      "text",
                                      "single_choice",
                                      "multiple_choice"
                                    ]
                                  },
                                  "solution": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "sort_order": {
                                    "type": "integer",
                                    "minimum": 1
                                  },
                                  "answers": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "id": {
                                          "type": "integer"
                                        },
                                        "answer": {
                                          "type": "string"
                                        },
                                        "is_correct": {
                                          "type": "boolean"
                                        },
                                        "sort_order": {
                                          "type": "integer",
                                          "minimum": 1
                                        }
                                      },
                                      "required": [
                                        "id",
                                        "answer",
                                        "is_correct",
                                        "sort_order"
                                      ]
                                    }
                                  },
                                  "created_at": {
                                    "type": "string",
                                    "format": "date-time"
                                  },
                                  "updated_at": {
                                    "type": "string",
                                    "format": "date-time"
                                  }
                                },
                                "required": [
                                  "id",
                                  "prompt",
                                  "question_type",
                                  "solution",
                                  "sort_order",
                                  "answers",
                                  "created_at",
                                  "updated_at"
                                ]
                              }
                            }
                          },
                          "required": [
                            "estimated_duration_minutes",
                            "instructions",
                            "questions"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "questions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "prompt": {
                            "type": "string"
                          },
                          "question_type": {
                            "type": "string",
                            "enum": [
                              "text",
                              "single_choice",
                              "multiple_choice"
                            ]
                          },
                          "solution": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "answers": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "answer": {
                                  "type": "string"
                                },
                                "is_correct": {
                                  "type": "boolean"
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                }
                              },
                              "required": [
                                "id",
                                "answer",
                                "is_correct",
                                "sort_order"
                              ]
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "prompt",
                          "question_type",
                          "solution",
                          "sort_order",
                          "answers",
                          "created_at",
                          "updated_at"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "section_id",
                    "title",
                    "content",
                    "type",
                    "is_preview",
                    "is_published",
                    "sort_order",
                    "video",
                    "attachments",
                    "assignment",
                    "questions",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "title",
              "description",
              "sort_order",
              "lessons",
              "created_at",
              "updated_at"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "description",
        "visibility",
        "is_draft",
        "delivery_text",
        "category",
        "level",
        "language",
        "subtitle",
        "author",
        "subcategory",
        "what_you_learn",
        "requirements",
        "certificate_enabled",
        "access_type",
        "access_duration_days",
        "enrollment_limit",
        "promo_video",
        "sections",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 50,
    "title": "Design foundations",
    "slug": "design-foundations",
    "description": "Build your first design with reusable templates.",
    "visibility": "HIDDEN",
    "is_draft": false,
    "delivery_text": "Open your course to get started.",
    "category": "design",
    "level": "beginner",
    "language": "en",
    "subtitle": null,
    "author": "Launch Lab",
    "subcategory": null,
    "what_you_learn": [
      "Customize a reusable template."
    ],
    "requirements": [
      "A web browser."
    ],
    "certificate_enabled": false,
    "access_type": "lifetime",
    "access_duration_days": null,
    "enrollment_limit": null,
    "promo_video": null,
    "sections": [
      {
        "id": 51,
        "title": "Getting started",
        "description": "Your first project.",
        "sort_order": 1,
        "lessons": [
          {
            "id": 52,
            "section_id": 51,
            "title": "Build your first design",
            "content": "Choose a template and add your project details.",
            "type": "lecture",
            "is_preview": false,
            "is_published": false,
            "sort_order": 1,
            "video": null,
            "attachments": [],
            "assignment": null,
            "questions": [],
            "created_at": "2026-09-01T12:00:00Z",
            "updated_at": "2026-09-01T12:00:00Z"
          }
        ],
        "created_at": "2026-09-01T12:00:00Z",
        "updated_at": "2026-09-01T12:00:00Z"
      }
    ],
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PUT /v2/courses/{course}

Update a course

Update course metadata, access configuration, delivery copy, or publication visibility. Public visibility requires a ready promotional video and at least one published lesson. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.courses.replace({
  "course": "string_example",
  "level": "beginner",
  "visibility": "HIDDEN"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.courses.replace(
    course="string_example",
    level="beginner",
    visibility="HIDDEN"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->courses()->replace(
    course: 'string_example',
    level: 'beginner',
    visibility: 'HIDDEN',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CoursesReplaceParams{}
    if err := json.Unmarshal([]byte("{\"level\":\"beginner\",\"visibility\":\"HIDDEN\"}"), params); err != nil { panic(err) }
    result, err := client.Courses().Replace(context.Background(), "string_example", params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Courses.ReplaceAsync(
    "string_example",
    new CoursesReplaceOptions
    {
        Level = JsonConvert.DeserializeObject<SdkReplaceCourseRequestApplicationJsonLevel>("\"beginner\"")!,
        Visibility = JsonConvert.DeserializeObject<CatalogVisibility>("\"HIDDEN\"")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.courses.replace(course = "string_example", level = app.sell.sellapp.types.SdkUpdateCourseRequestApplicationJsonLevel("beginner"), visibility = app.sell.sellapp.types.CatalogVisibility("HIDDEN"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.courses.replace(
  course: "string_example",
  level: "beginner",
  visibility: "HIDDEN"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::courses::ReplaceParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceParams::new(serde_json::from_str("{\"level\":\"beginner\",\"visibility\":\"HIDDEN\"}")?);
    let result = client.courses().replace("string_example", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Courses.replace(client, "string_example", %{"level" => "beginner", "visibility" => "HIDDEN"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp courses replace test_course --level beginner --visibility HIDDEN

```

- Method: `PUT`

- Path: `/v2/courses/{course}`

- Full URL: `https://sell.app/api/v2/courses/{course}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_COURSE_ID='replace-me'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/courses/${SELLAPP_COURSE_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "level": "beginner",
  "visibility": "HIDDEN"
}'
```

## Path Parameters
- `course` (`string`, required): The course path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "category": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "development",
        "business",
        "marketing",
        "design",
        "finance",
        "it-software",
        "personal-development",
        "productivity",
        "other",
        null
      ]
    },
    "level": {
      "type": "string",
      "enum": [
        "all_levels",
        "beginner",
        "intermediate",
        "advanced"
      ]
    },
    "language": {
      "type": "string",
      "maxLength": 255
    },
    "subtitle": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 120
    },
    "author": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 120
    },
    "subcategory": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 255
    },
    "what_you_learn": {
      "type": "array",
      "maxItems": 50,
      "items": {
        "type": "string",
        "maxLength": 255
      }
    },
    "requirements": {
      "type": "array",
      "maxItems": 50,
      "items": {
        "type": "string",
        "maxLength": 255
      }
    },
    "certificate_enabled": {
      "type": "boolean"
    },
    "access_type": {
      "type": "string",
      "enum": [
        "lifetime",
        "limited"
      ]
    },
    "access_duration_days": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1,
      "maximum": 3650,
      "description": "Required when access_type is limited; cleared otherwise."
    },
    "enrollment_limit": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "delivery_text": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 65535
    },
    "visibility": {
      "type": "string",
      "enum": [
        "PUBLIC",
        "ON_HOLD",
        "HIDDEN",
        "PRIVATE"
      ]
    },
    "expected_updated_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
```

Example (minimal):

```json
{
  "level": "beginner",
  "visibility": "HIDDEN"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ]
        },
        "is_draft": {
          "type": "boolean"
        },
        "delivery_text": {
          "type": [
            "string",
            "null"
          ]
        },
        "category": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "development",
            "business",
            "marketing",
            "design",
            "finance",
            "it-software",
            "personal-development",
            "productivity",
            "other",
            null
          ]
        },
        "level": {
          "type": "string",
          "enum": [
            "all_levels",
            "beginner",
            "intermediate",
            "advanced"
          ]
        },
        "language": {
          "type": "string"
        },
        "subtitle": {
          "type": [
            "string",
            "null"
          ]
        },
        "author": {
          "type": [
            "string",
            "null"
          ]
        },
        "subcategory": {
          "type": [
            "string",
            "null"
          ]
        },
        "what_you_learn": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "requirements": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "certificate_enabled": {
          "type": "boolean"
        },
        "access_type": {
          "type": "string",
          "enum": [
            "lifetime",
            "limited"
          ]
        },
        "access_duration_days": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1,
          "maximum": 3650
        },
        "enrollment_limit": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1
        },
        "promo_video": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "mux_playback_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "mux_status": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "duration_seconds": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                }
              },
              "required": [
                "mux_playback_id",
                "mux_status",
                "duration_seconds"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "sections": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sort_order": {
                "type": "integer",
                "minimum": 1
              },
              "lessons": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "section_id": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "content": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "lecture",
                        "video",
                        "text",
                        "quiz",
                        "assignment"
                      ]
                    },
                    "is_preview": {
                      "type": "boolean"
                    },
                    "is_published": {
                      "type": "boolean"
                    },
                    "sort_order": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "video": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "source": {
                              "type": "string",
                              "enum": [
                                "mux",
                                "external"
                              ]
                            },
                            "external_url": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "format": "uri"
                            },
                            "mux_playback_id": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "mux_status": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "duration_seconds": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 0
                            }
                          },
                          "required": [
                            "source",
                            "external_url",
                            "mux_playback_id",
                            "mux_status",
                            "duration_seconds"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attachments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "title": {
                            "type": "string"
                          },
                          "mime_type": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "size_bytes": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "minimum": 0
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          }
                        },
                        "required": [
                          "id",
                          "title",
                          "mime_type",
                          "size_bytes",
                          "sort_order"
                        ]
                      }
                    },
                    "assignment": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "estimated_duration_minutes": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 1,
                              "maximum": 1440
                            },
                            "instructions": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "questions": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "integer"
                                  },
                                  "prompt": {
                                    "type": "string"
                                  },
                                  "question_type": {
                                    "type": "string",
                                    "enum": [
                                      "text",
                                      "single_choice",
                                      "multiple_choice"
                                    ]
                                  },
                                  "solution": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "sort_order": {
                                    "type": "integer",
                                    "minimum": 1
                                  },
                                  "answers": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "id": {
                                          "type": "integer"
                                        },
                                        "answer": {
                                          "type": "string"
                                        },
                                        "is_correct": {
                                          "type": "boolean"
                                        },
                                        "sort_order": {
                                          "type": "integer",
                                          "minimum": 1
                                        }
                                      },
                                      "required": [
                                        "id",
                                        "answer",
                                        "is_correct",
                                        "sort_order"
                                      ]
                                    }
                                  },
                                  "created_at": {
                                    "type": "string",
                                    "format": "date-time"
                                  },
                                  "updated_at": {
                                    "type": "string",
                                    "format": "date-time"
                                  }
                                },
                                "required": [
                                  "id",
                                  "prompt",
                                  "question_type",
                                  "solution",
                                  "sort_order",
                                  "answers",
                                  "created_at",
                                  "updated_at"
                                ]
                              }
                            }
                          },
                          "required": [
                            "estimated_duration_minutes",
                            "instructions",
                            "questions"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "questions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "prompt": {
                            "type": "string"
                          },
                          "question_type": {
                            "type": "string",
                            "enum": [
                              "text",
                              "single_choice",
                              "multiple_choice"
                            ]
                          },
                          "solution": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "sort_order": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "answers": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer"
                                },
                                "answer": {
                                  "type": "string"
                                },
                                "is_correct": {
                                  "type": "boolean"
                                },
                                "sort_order": {
                                  "type": "integer",
                                  "minimum": 1
                                }
                              },
                              "required": [
                                "id",
                                "answer",
                                "is_correct",
                                "sort_order"
                              ]
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "prompt",
                          "question_type",
                          "solution",
                          "sort_order",
                          "answers",
                          "created_at",
                          "updated_at"
                        ]
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "section_id",
                    "title",
                    "content",
                    "type",
                    "is_preview",
                    "is_published",
                    "sort_order",
                    "video",
                    "attachments",
                    "assignment",
                    "questions",
                    "created_at",
                    "updated_at"
                  ]
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "title",
              "description",
              "sort_order",
              "lessons",
              "created_at",
              "updated_at"
            ]
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "description",
        "visibility",
        "is_draft",
        "delivery_text",
        "category",
        "level",
        "language",
        "subtitle",
        "author",
        "subcategory",
        "what_you_learn",
        "requirements",
        "certificate_enabled",
        "access_type",
        "access_duration_days",
        "enrollment_limit",
        "promo_video",
        "sections",
        "created_at",
        "updated_at"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 50,
    "title": "Design foundations",
    "slug": "design-foundations",
    "description": "Build your first design with reusable templates.",
    "visibility": "HIDDEN",
    "is_draft": false,
    "delivery_text": "Open your course to get started.",
    "category": "design",
    "level": "beginner",
    "language": "en",
    "subtitle": null,
    "author": "Launch Lab",
    "subcategory": null,
    "what_you_learn": [
      "Customize a reusable template."
    ],
    "requirements": [
      "A web browser."
    ],
    "certificate_enabled": false,
    "access_type": "lifetime",
    "access_duration_days": null,
    "enrollment_limit": null,
    "promo_video": null,
    "sections": [
      {
        "id": 51,
        "title": "Getting started",
        "description": "Your first project.",
        "sort_order": 1,
        "lessons": [
          {
            "id": 52,
            "section_id": 51,
            "title": "Build your first design",
            "content": "Choose a template and add your project details.",
            "type": "lecture",
            "is_preview": false,
            "is_published": false,
            "sort_order": 1,
            "video": null,
            "attachments": [],
            "assignment": null,
            "questions": [],
            "created_at": "2026-09-01T12:00:00Z",
            "updated_at": "2026-09-01T12:00:00Z"
          }
        ],
        "created_at": "2026-09-01T12:00:00Z",
        "updated_at": "2026-09-01T12:00:00Z"
      }
    ],
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Customer portal API (/docs/api/customer-portal)

These routes accept a customer-session bearer token—not a seller API key. Every resource is limited to the signed-in customer and redacted for customer use. Read subscription capabilities immediately before showing an action.

## GET /v2/customer-portal/me

Retrieve the signed-in customer

Customer-session bearer authentication; resource is redacted.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.getCustomerPortalProfile();
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.get_customer_portal_profile()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->getCustomerPortalProfile();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    result, err := client.CustomerPortal().GetProfile(context.Background())
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.GetProfileAsync();
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.getProfile()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.get_customer_portal_profile
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let result = client.customer_portal().get_customer_portal_profile().await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.get_customer_portal_profile(client)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal get-customer-portal-profile

```

- Method: `GET`

- Path: `/v2/customer-portal/me`

- Full URL: `https://sell.app/api/v2/customer-portal/me`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/me" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "email",
        "external_id",
        "name",
        "locale",
        "metadata"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "external_id": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "name": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "locale": {
          "type": [
            "string",
            "null"
          ],
          "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
        },
        "metadata": {
          "type": "object",
          "maxProperties": 50,
          "additionalProperties": {
            "oneOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 314,
    "email": "maya.chen@example.com",
    "external_id": "crm_maya_314",
    "name": "Maya Chen",
    "locale": "en-GB",
    "metadata": {
      "plan": "standard",
      "seats": 3
    }
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v2/customer-portal/me

Update the signed-in customer

Update customer-safe profile fields.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.updateCustomerPortalProfile({
  "locale": "en-US"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.update_customer_portal_profile(locale="en-US")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->updateCustomerPortalProfile(locale: 'en-US');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    params := &sellapp.CustomerPortalUpdateProfileParams{}
    if err := json.Unmarshal([]byte("{\"locale\":\"en-US\"}"), params); err != nil { panic(err) }
    result, err := client.CustomerPortal().UpdateProfile(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.UpdateProfileAsync(new CustomerPortalUpdateProfileOptions
    {
        Locale = JsonConvert.DeserializeObject<string?>("\"en-US\"")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.updateProfile(locale = app.sell.sellapp.common.http.PatchField.Present("en-US"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.update_customer_portal_profile(locale: "en-US")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customer_portal::UpdateCustomerPortalProfileParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let mut params = UpdateCustomerPortalProfileParams::new(serde_json::from_str("{\"locale\":\"en-US\"}")?);
    let result = client.customer_portal().update_customer_portal_profile(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.update_customer_portal_profile(client, %{"locale" => "en-US"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal update-customer-portal-profile --locale en-US --yes

```

- Method: `PATCH`

- Path: `/v2/customer-portal/me`

- Full URL: `https://sell.app/api/v2/customer-portal/me`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/me" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "locale": "en-US"
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "format": "email",
      "maxLength": 255
    },
    "name": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 255
    },
    "locale": {
      "type": [
        "string",
        "null"
      ],
      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
      "maxLength": 35
    },
    "metadata": {
      "type": "object",
      "maxProperties": 50,
      "propertyNames": {
        "maxLength": 40
      },
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string",
            "maxLength": 500
          },
          {
            "type": "number"
          },
          {
            "type": "boolean"
          }
        ]
      }
    }
  }
}
```

Example:

```json
{
  "locale": "en-US"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "email",
        "external_id",
        "name",
        "locale",
        "metadata"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "external_id": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "name": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "locale": {
          "type": [
            "string",
            "null"
          ],
          "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
        },
        "metadata": {
          "type": "object",
          "maxProperties": 50,
          "additionalProperties": {
            "oneOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 314,
    "email": "maya.chen@example.com",
    "external_id": "crm_maya_314",
    "name": "Maya Chen",
    "locale": "en-US",
    "metadata": {
      "plan": "standard",
      "seats": 3
    }
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/customer-portal/orders

List customer orders

List purchases belonging to the customer session.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.listCustomerPortalOrders();
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.list_customer_portal_orders()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->listCustomerPortalOrders();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    page := client.CustomerPortal().ListOrders(context.Background())
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.ListOrdersAsync();
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.listOrders()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.list_customer_portal_orders
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let result = client.customer_portal().list_customer_portal_orders().await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.list_customer_portal_orders(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal list-customer-portal-orders

```

- Method: `GET`

- Path: `/v2/customer-portal/orders`

- Full URL: `https://sell.app/api/v2/customer-portal/orders`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/orders" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data",
    "links",
    "meta"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "description": "The customer's purchase summary. Seller-only payment details and status timelines are not included.",
        "required": [
          "id",
          "status",
          "currency",
          "subtotal_cents",
          "total_cents",
          "line_items",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "status": {
            "type": "string"
          },
          "currency": {
            "type": "string",
            "description": "Uppercase currency code for the order amounts."
          },
          "subtotal_cents": {
            "type": "integer",
            "description": "Order subtotal in minor currency units; 1999 means USD 19.99 when currency is USD."
          },
          "total_cents": {
            "type": "integer",
            "description": "Order total including tax, in minor currency units."
          },
          "line_items": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "A purchased variant visible to the signed-in customer.",
              "required": [
                "id",
                "product_id",
                "product_variant_id",
                "product_title",
                "variant_title",
                "quantity",
                "status"
              ],
              "properties": {
                "id": {
                  "type": "integer",
                  "description": "The purchased line item ID."
                },
                "product_id": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "product_variant_id": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "product_title": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "variant_title": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "quantity": {
                  "type": "integer"
                },
                "status": {
                  "type": "string",
                  "description": "The current state of this purchased line item."
                }
              }
            }
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "id": 9001,
      "status": "COMPLETED",
      "currency": "USD",
      "subtotal_cents": 1999,
      "total_cents": 1999,
      "line_items": [
        {
          "id": 501,
          "product_id": 120,
          "product_variant_id": 4321,
          "product_title": "Founder memo circle",
          "variant_title": "Monthly membership",
          "quantity": 1,
          "status": "COMPLETED"
        }
      ],
      "created_at": "2026-09-04T09:10:00.000Z",
      "updated_at": "2026-09-04T09:12:00.000Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/customer-portal/orders?page=1",
    "last": "https://sell.app/api/v2/customer-portal/orders?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/customer-portal/orders",
    "per_page": 20,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/customer-portal/orders?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/customer-portal/orders/{order}

Retrieve a customer order

Retrieve a purchase belonging to the customer session.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.getCustomerPortalOrder({
  "order": 9001
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.get_customer_portal_order(order=9001)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->getCustomerPortalOrder(order: 9001);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    result, err := client.CustomerPortal().GetOrder(context.Background(), 9001)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.GetOrderAsync("9001");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.getOrder(order = "9001")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.get_customer_portal_order(order: 9001)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let result = client.customer_portal().get_customer_portal_order("9001").await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.get_customer_portal_order(client, 9001)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal get-customer-portal-order 9001

```

- Method: `GET`

- Path: `/v2/customer-portal/orders/{order}`

- Full URL: `https://sell.app/api/v2/customer-portal/orders/{order}`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_ORDER_ID='9001'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/orders/${SELLAPP_ORDER_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}"
```

## Path Parameters
- `order` (`integer`, required): The order identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "The customer's purchase summary. Seller-only payment details and status timelines are not included.",
      "required": [
        "id",
        "status",
        "currency",
        "subtotal_cents",
        "total_cents",
        "line_items",
        "created_at",
        "updated_at"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "status": {
          "type": "string"
        },
        "currency": {
          "type": "string",
          "description": "Uppercase currency code for the order amounts."
        },
        "subtotal_cents": {
          "type": "integer",
          "description": "Order subtotal in minor currency units; 1999 means USD 19.99 when currency is USD."
        },
        "total_cents": {
          "type": "integer",
          "description": "Order total including tax, in minor currency units."
        },
        "line_items": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "A purchased variant visible to the signed-in customer.",
            "required": [
              "id",
              "product_id",
              "product_variant_id",
              "product_title",
              "variant_title",
              "quantity",
              "status"
            ],
            "properties": {
              "id": {
                "type": "integer",
                "description": "The purchased line item ID."
              },
              "product_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "product_variant_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "product_title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "variant_title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "quantity": {
                "type": "integer"
              },
              "status": {
                "type": "string",
                "description": "The current state of this purchased line item."
              }
            }
          }
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 9001,
    "status": "COMPLETED",
    "currency": "USD",
    "subtotal_cents": 1999,
    "total_cents": 1999,
    "line_items": [
      {
        "id": 501,
        "product_id": 120,
        "product_variant_id": 4321,
        "product_title": "Founder memo circle",
        "variant_title": "Monthly membership",
        "quantity": 1,
        "status": "COMPLETED"
      }
    ],
    "created_at": "2026-09-04T09:10:00.000Z",
    "updated_at": "2026-09-04T09:12:00.000Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/customer-portal/subscriptions

List customer subscriptions

List subscriptions belonging to the customer session.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.listCustomerPortalSubscriptions();
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.list_customer_portal_subscriptions()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->listCustomerPortalSubscriptions();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    result, err := client.CustomerPortal().ListSubscriptions(context.Background())
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.ListSubscriptionsAsync();
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.listSubscriptions()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.list_customer_portal_subscriptions
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let result = client.customer_portal().list_customer_portal_subscriptions().await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.list_customer_portal_subscriptions(client)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal list-customer-portal-subscriptions

```

- Method: `GET`

- Path: `/v2/customer-portal/subscriptions`

- Full URL: `https://sell.app/api/v2/customer-portal/subscriptions`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/subscriptions" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "status",
          "provider_subscription_id",
          "provider_customer_id",
          "customer"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "status": {
            "type": "string"
          },
          "subscription_id": {
            "type": [
              "string",
              "null"
            ],
            "deprecated": true
          },
          "customer_id": {
            "type": [
              "string",
              "null"
            ],
            "deprecated": true
          },
          "provider_subscription_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "provider_customer_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "customer": {
            "type": "object",
            "required": [
              "id",
              "email",
              "external_id",
              "name",
              "locale",
              "metadata"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "email": {
                "type": "string",
                "format": "email"
              },
              "external_id": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 255
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 255
              },
              "locale": {
                "type": [
                  "string",
                  "null"
                ],
                "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
              },
              "metadata": {
                "type": "object",
                "maxProperties": 50,
                "additionalProperties": {
                  "oneOf": [
                    {
                      "type": "string",
                      "maxLength": 500
                    },
                    {
                      "type": "number"
                    },
                    {
                      "type": "boolean"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              }
            }
          },
          "product_variant_id": {
            "type": "integer"
          }
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "id": 991,
      "status": "active",
      "subscription_id": "sub_example",
      "customer_id": "cus_maya",
      "provider_subscription_id": "sub_example",
      "provider_customer_id": "cus_maya",
      "customer": {
        "id": 314,
        "email": "maya.chen@example.com",
        "external_id": "crm_maya_314",
        "name": "Maya Chen",
        "locale": "en-GB",
        "metadata": {
          "plan": "standard",
          "seats": 3
        }
      },
      "product_variant_id": 84
    }
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/customer-portal/subscriptions/{subscription}

Retrieve a customer subscription

Retrieve a subscription belonging to the customer session.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.getCustomerPortalSubscription({
  "subscription": 991
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.get_customer_portal_subscription(subscription=991)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->getCustomerPortalSubscription(subscription: 991);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    result, err := client.CustomerPortal().GetSubscription(context.Background(), 991)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.GetSubscriptionAsync("991");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.getSubscription(subscription = "991")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.get_customer_portal_subscription(subscription: 991)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let result = client.customer_portal().get_customer_portal_subscription("991").await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.get_customer_portal_subscription(client, 991)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal get-customer-portal-subscription 991

```

- Method: `GET`

- Path: `/v2/customer-portal/subscriptions/{subscription}`

- Full URL: `https://sell.app/api/v2/customer-portal/subscriptions/{subscription}`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_SUBSCRIPTION_ID='991'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/subscriptions/${SELLAPP_SUBSCRIPTION_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}"
```

## Path Parameters
- `subscription` (`integer`, required): The subscription identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "status",
        "provider_subscription_id",
        "provider_customer_id",
        "customer"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "status": {
          "type": "string"
        },
        "subscription_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "customer_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "provider_subscription_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "provider_customer_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "customer": {
          "type": "object",
          "required": [
            "id",
            "email",
            "external_id",
            "name",
            "locale",
            "metadata"
          ],
          "properties": {
            "id": {
              "type": "integer"
            },
            "email": {
              "type": "string",
              "format": "email"
            },
            "external_id": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "locale": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
            },
            "metadata": {
              "type": "object",
              "maxProperties": 50,
              "additionalProperties": {
                "oneOf": [
                  {
                    "type": "string",
                    "maxLength": 500
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        },
        "product_variant_id": {
          "type": "integer"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 991,
    "status": "active",
    "subscription_id": "sub_example",
    "customer_id": "cus_maya",
    "provider_subscription_id": "sub_example",
    "provider_customer_id": "cus_maya",
    "customer": {
      "id": 314,
      "email": "maya.chen@example.com",
      "external_id": "crm_maya_314",
      "name": "Maya Chen",
      "locale": "en-GB",
      "metadata": {
        "plan": "standard",
        "seats": 3
      }
    },
    "product_variant_id": 84
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/customer-portal/subscriptions/{subscription}/capabilities

Retrieve subscription capabilities

Read immediately before displaying lifecycle controls.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.getCustomerPortalSubscriptionCapabilities({
  "subscription": 42
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.get_customer_portal_subscription_capabilities(subscription=42)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->getCustomerPortalSubscriptionCapabilities(subscription: 42);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    result, err := client.CustomerPortal().GetSubscriptionCapabilities(context.Background(), 42)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.GetSubscriptionCapabilitiesAsync("42");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.getSubscriptionCapabilities(subscription = "42")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.get_customer_portal_subscription_capabilities(subscription: 42)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let result = client.customer_portal().get_customer_portal_subscription_capabilities("42").await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.get_customer_portal_subscription_capabilities(client, 42)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal get-customer-portal-subscription-capabilities 42

```

- Method: `GET`

- Path: `/v2/customer-portal/subscriptions/{subscription}/capabilities`

- Full URL: `https://sell.app/api/v2/customer-portal/subscriptions/{subscription}/capabilities`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_SUBSCRIPTION_ID='42'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/subscriptions/${SELLAPP_SUBSCRIPTION_ID}/capabilities" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}"
```

## Path Parameters
- `subscription` (`integer`, required): The subscription identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "subscription_id",
        "capabilities"
      ],
      "properties": {
        "subscription_id": {
          "type": "integer"
        },
        "capabilities": {
          "type": "object",
          "additionalProperties": {
            "type": "object",
            "required": [
              "available"
            ],
            "properties": {
              "available": {
                "type": "boolean"
              },
              "reason": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "subscription_id": 991,
    "capabilities": {
      "pause": {
        "available": true
      },
      "resume": {
        "available": false
      }
    }
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/customer-portal/entitlements

List customer entitlements

List the customer's purchase access summary without fulfillment secrets.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.listCustomerPortalEntitlements();
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.list_customer_portal_entitlements()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->listCustomerPortalEntitlements();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    result, err := client.CustomerPortal().ListEntitlements(context.Background())
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.ListEntitlementsAsync();
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.listEntitlements()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.list_customer_portal_entitlements
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let result = client.customer_portal().list_customer_portal_entitlements().await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.list_customer_portal_entitlements(client)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal list-customer-portal-entitlements

```

- Method: `GET`

- Path: `/v2/customer-portal/entitlements`

- Full URL: `https://sell.app/api/v2/customer-portal/entitlements`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/entitlements" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "state",
          "customer_id",
          "subject"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z_]+:[A-Za-z0-9-]+$"
          },
          "kind": {
            "type": "string",
            "enum": [
              "delivered_product",
              "license",
              "community_grant",
              "booking",
              "subscription_access"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "suspended",
              "expired",
              "revoked",
              "failed",
              "action_required"
            ]
          },
          "customer_id": {
            "type": "integer"
          },
          "subject": {
            "type": "object",
            "required": [
              "type",
              "id",
              "name"
            ],
            "properties": {
              "type": {
                "type": "string"
              },
              "id": {
                "type": [
                  "integer",
                  "string"
                ]
              },
              "name": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "id": "subscription_access:991",
      "kind": "subscription_access",
      "state": "active",
      "customer_id": 314,
      "subject": {
        "type": "product_variant",
        "id": 84,
        "name": "Design kit — monthly"
      }
    }
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/customer-portal/subscriptions/{productSubscription}/actions/cancel-period-end

Cancel at period end

Cancel at period end. Read capabilities first; state conflicts return 409.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.cancelCustomerSubscriptionAtPeriodEnd({
  "productSubscription": 42,
  "reason": "Customer requested this change"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.cancel_customer_subscription_at_period_end(
    product_subscription=42,
    reason="Customer requested this change"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->cancelCustomerSubscriptionAtPeriodEnd(
    productSubscription: 42,
    reason: 'Customer requested this change',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    params := &sellapp.CustomerPortalCancelSubscriptionAtPeriodEndParams{}
    if err := json.Unmarshal([]byte("{\"reason\":\"Customer requested this change\"}"), params); err != nil { panic(err) }
    result, err := client.CustomerPortal().CancelSubscriptionAtPeriodEnd(context.Background(), 42, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.CancelSubscriptionAtPeriodEndAsync(
    "42",
    new CustomerPortalCancelSubscriptionAtPeriodEndOptions
    {
        Reason = "Customer requested this change",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.cancelSubscriptionAtPeriodEnd(productSubscription = "42", reason = "Customer requested this change")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.cancel_customer_subscription_at_period_end(
  product_subscription: 42,
  reason: "Customer requested this change"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customer_portal::CancelCustomerSubscriptionAtPeriodEndParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let mut params = CancelCustomerSubscriptionAtPeriodEndParams::new(serde_json::from_str("{\"reason\":\"Customer requested this change\"}")?);
    let result = client.customer_portal().cancel_customer_subscription_at_period_end("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.cancel_customer_subscription_at_period_end(client, 42, %{"reason" => "Customer requested this change"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal cancel-customer-subscription-at-period-end 42 --reason 'Customer requested this change' --yes

```

- Method: `POST`

- Path: `/v2/customer-portal/subscriptions/{productSubscription}/actions/cancel-period-end`

- Full URL: `https://sell.app/api/v2/customer-portal/subscriptions/{productSubscription}/actions/cancel-period-end`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_SUBSCRIPTION_ID='42'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/subscriptions/${SELLAPP_PRODUCT_SUBSCRIPTION_ID}/actions/cancel-period-end" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}" \
  --header 'Idempotency-Key: project-library-2026-09-04' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "reason": "Customer requested this change"
}'
```

## Path Parameters
- `productSubscription` (`integer`, required): The productSubscription identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `Idempotency-Key` (`string`, required): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "preview_id": {
      "type": "string"
    },
    "product_variant_id": {
      "type": "integer"
    },
    "renewal_date": {
      "type": "string",
      "format": "date"
    },
    "return_url": {
      "type": "string",
      "format": "uri"
    },
    "reason": {
      "type": "string"
    }
  }
}
```

Example:

```json
{
  "reason": "Customer requested this change"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "status",
        "provider_subscription_id",
        "provider_customer_id",
        "customer"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "status": {
          "type": "string"
        },
        "subscription_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "customer_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "provider_subscription_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "provider_customer_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "customer": {
          "type": "object",
          "required": [
            "id",
            "email",
            "external_id",
            "name",
            "locale",
            "metadata"
          ],
          "properties": {
            "id": {
              "type": "integer"
            },
            "email": {
              "type": "string",
              "format": "email"
            },
            "external_id": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "locale": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
            },
            "metadata": {
              "type": "object",
              "maxProperties": 50,
              "additionalProperties": {
                "oneOf": [
                  {
                    "type": "string",
                    "maxLength": 500
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        },
        "product_variant_id": {
          "type": "integer"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 991,
    "status": "active",
    "subscription_id": "sub_example",
    "customer_id": "cus_maya",
    "provider_subscription_id": "sub_example",
    "provider_customer_id": "cus_maya",
    "customer": {
      "id": 314,
      "email": "maya.chen@example.com",
      "external_id": "crm_maya_314",
      "name": "Maya Chen",
      "locale": "en-GB",
      "metadata": {
        "plan": "standard",
        "seats": 3
      }
    },
    "product_variant_id": 84
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/customer-portal/subscriptions/{productSubscription}/actions/cancel-immediately

Cancel immediately

Cancel immediately. Read capabilities first; state conflicts return 409.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.cancelCustomerSubscriptionImmediately({
  "productSubscription": 42,
  "reason": "Customer requested this change"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.cancel_customer_subscription_immediately(
    product_subscription=42,
    reason="Customer requested this change"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->cancelCustomerSubscriptionImmediately(
    productSubscription: 42,
    reason: 'Customer requested this change',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    params := &sellapp.CustomerPortalCancelSubscriptionImmediatelyParams{}
    if err := json.Unmarshal([]byte("{\"reason\":\"Customer requested this change\"}"), params); err != nil { panic(err) }
    result, err := client.CustomerPortal().CancelSubscriptionImmediately(context.Background(), 42, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.CancelSubscriptionImmediatelyAsync(
    "42",
    new CustomerPortalCancelSubscriptionImmediatelyOptions
    {
        Reason = "Customer requested this change",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.cancelSubscriptionImmediately(productSubscription = "42", reason = "Customer requested this change")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.cancel_customer_subscription_immediately(
  product_subscription: 42,
  reason: "Customer requested this change"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customer_portal::CancelCustomerSubscriptionImmediatelyParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let mut params = CancelCustomerSubscriptionImmediatelyParams::new(serde_json::from_str("{\"reason\":\"Customer requested this change\"}")?);
    let result = client.customer_portal().cancel_customer_subscription_immediately("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.cancel_customer_subscription_immediately(client, 42, %{"reason" => "Customer requested this change"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal cancel-customer-subscription-immediately 42 --reason 'Customer requested this change' --yes

```

- Method: `POST`

- Path: `/v2/customer-portal/subscriptions/{productSubscription}/actions/cancel-immediately`

- Full URL: `https://sell.app/api/v2/customer-portal/subscriptions/{productSubscription}/actions/cancel-immediately`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_SUBSCRIPTION_ID='42'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/subscriptions/${SELLAPP_PRODUCT_SUBSCRIPTION_ID}/actions/cancel-immediately" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}" \
  --header 'Idempotency-Key: project-library-2026-09-04' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "reason": "Customer requested this change"
}'
```

## Path Parameters
- `productSubscription` (`integer`, required): The productSubscription identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `Idempotency-Key` (`string`, required): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "preview_id": {
      "type": "string"
    },
    "product_variant_id": {
      "type": "integer"
    },
    "renewal_date": {
      "type": "string",
      "format": "date"
    },
    "return_url": {
      "type": "string",
      "format": "uri"
    },
    "reason": {
      "type": "string"
    }
  }
}
```

Example:

```json
{
  "reason": "Customer requested this change"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "status",
        "provider_subscription_id",
        "provider_customer_id",
        "customer"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "status": {
          "type": "string"
        },
        "subscription_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "customer_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "provider_subscription_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "provider_customer_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "customer": {
          "type": "object",
          "required": [
            "id",
            "email",
            "external_id",
            "name",
            "locale",
            "metadata"
          ],
          "properties": {
            "id": {
              "type": "integer"
            },
            "email": {
              "type": "string",
              "format": "email"
            },
            "external_id": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "locale": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
            },
            "metadata": {
              "type": "object",
              "maxProperties": 50,
              "additionalProperties": {
                "oneOf": [
                  {
                    "type": "string",
                    "maxLength": 500
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        },
        "product_variant_id": {
          "type": "integer"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 991,
    "status": "active",
    "subscription_id": "sub_example",
    "customer_id": "cus_maya",
    "provider_subscription_id": "sub_example",
    "provider_customer_id": "cus_maya",
    "customer": {
      "id": 314,
      "email": "maya.chen@example.com",
      "external_id": "crm_maya_314",
      "name": "Maya Chen",
      "locale": "en-GB",
      "metadata": {
        "plan": "standard",
        "seats": 3
      }
    },
    "product_variant_id": 84
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/customer-portal/subscriptions/{productSubscription}/actions/pause

Pause a subscription

Pause a subscription. Read capabilities first; state conflicts return 409.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.pauseCustomerSubscription({
  "productSubscription": 42,
  "reason": "Customer requested this change"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.pause_customer_subscription(
    product_subscription=42,
    reason="Customer requested this change"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->pauseCustomerSubscription(
    productSubscription: 42,
    reason: 'Customer requested this change',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    params := &sellapp.CustomerPortalPauseSubscriptionParams{}
    if err := json.Unmarshal([]byte("{\"reason\":\"Customer requested this change\"}"), params); err != nil { panic(err) }
    result, err := client.CustomerPortal().PauseSubscription(context.Background(), 42, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.PauseSubscriptionAsync(
    "42",
    new CustomerPortalPauseSubscriptionOptions
    {
        Reason = "Customer requested this change",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.pauseSubscription(productSubscription = "42", reason = "Customer requested this change")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.pause_customer_subscription(
  product_subscription: 42,
  reason: "Customer requested this change"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customer_portal::PauseCustomerSubscriptionParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let mut params = PauseCustomerSubscriptionParams::new(serde_json::from_str("{\"reason\":\"Customer requested this change\"}")?);
    let result = client.customer_portal().pause_customer_subscription("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.pause_customer_subscription(client, 42, %{"reason" => "Customer requested this change"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal pause-customer-subscription 42 --reason 'Customer requested this change' --yes

```

- Method: `POST`

- Path: `/v2/customer-portal/subscriptions/{productSubscription}/actions/pause`

- Full URL: `https://sell.app/api/v2/customer-portal/subscriptions/{productSubscription}/actions/pause`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_SUBSCRIPTION_ID='42'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/subscriptions/${SELLAPP_PRODUCT_SUBSCRIPTION_ID}/actions/pause" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}" \
  --header 'Idempotency-Key: project-library-2026-09-04' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "reason": "Customer requested this change"
}'
```

## Path Parameters
- `productSubscription` (`integer`, required): The productSubscription identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `Idempotency-Key` (`string`, required): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "preview_id": {
      "type": "string"
    },
    "product_variant_id": {
      "type": "integer"
    },
    "renewal_date": {
      "type": "string",
      "format": "date"
    },
    "return_url": {
      "type": "string",
      "format": "uri"
    },
    "reason": {
      "type": "string"
    }
  }
}
```

Example:

```json
{
  "reason": "Customer requested this change"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "status",
        "provider_subscription_id",
        "provider_customer_id",
        "customer"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "status": {
          "type": "string"
        },
        "subscription_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "customer_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "provider_subscription_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "provider_customer_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "customer": {
          "type": "object",
          "required": [
            "id",
            "email",
            "external_id",
            "name",
            "locale",
            "metadata"
          ],
          "properties": {
            "id": {
              "type": "integer"
            },
            "email": {
              "type": "string",
              "format": "email"
            },
            "external_id": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "locale": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
            },
            "metadata": {
              "type": "object",
              "maxProperties": 50,
              "additionalProperties": {
                "oneOf": [
                  {
                    "type": "string",
                    "maxLength": 500
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        },
        "product_variant_id": {
          "type": "integer"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 991,
    "status": "active",
    "subscription_id": "sub_example",
    "customer_id": "cus_maya",
    "provider_subscription_id": "sub_example",
    "provider_customer_id": "cus_maya",
    "customer": {
      "id": 314,
      "email": "maya.chen@example.com",
      "external_id": "crm_maya_314",
      "name": "Maya Chen",
      "locale": "en-GB",
      "metadata": {
        "plan": "standard",
        "seats": 3
      }
    },
    "product_variant_id": 84
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/customer-portal/subscriptions/{productSubscription}/actions/resume

Resume a subscription

Resume a subscription. Read capabilities first; state conflicts return 409.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.resumeCustomerSubscription({
  "productSubscription": 42,
  "reason": "Customer requested this change"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.resume_customer_subscription(
    product_subscription=42,
    reason="Customer requested this change"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->resumeCustomerSubscription(
    productSubscription: 42,
    reason: 'Customer requested this change',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    params := &sellapp.CustomerPortalResumeSubscriptionParams{}
    if err := json.Unmarshal([]byte("{\"reason\":\"Customer requested this change\"}"), params); err != nil { panic(err) }
    result, err := client.CustomerPortal().ResumeSubscription(context.Background(), 42, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.ResumeSubscriptionAsync(
    "42",
    new CustomerPortalResumeSubscriptionOptions
    {
        Reason = "Customer requested this change",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.resumeSubscription(productSubscription = "42", reason = "Customer requested this change")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.resume_customer_subscription(
  product_subscription: 42,
  reason: "Customer requested this change"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customer_portal::ResumeCustomerSubscriptionParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let mut params = ResumeCustomerSubscriptionParams::new(serde_json::from_str("{\"reason\":\"Customer requested this change\"}")?);
    let result = client.customer_portal().resume_customer_subscription("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.resume_customer_subscription(client, 42, %{"reason" => "Customer requested this change"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal resume-customer-subscription 42 --reason 'Customer requested this change' --yes

```

- Method: `POST`

- Path: `/v2/customer-portal/subscriptions/{productSubscription}/actions/resume`

- Full URL: `https://sell.app/api/v2/customer-portal/subscriptions/{productSubscription}/actions/resume`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_SUBSCRIPTION_ID='42'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/subscriptions/${SELLAPP_PRODUCT_SUBSCRIPTION_ID}/actions/resume" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}" \
  --header 'Idempotency-Key: project-library-2026-09-04' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "reason": "Customer requested this change"
}'
```

## Path Parameters
- `productSubscription` (`integer`, required): The productSubscription identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `Idempotency-Key` (`string`, required): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "preview_id": {
      "type": "string"
    },
    "product_variant_id": {
      "type": "integer"
    },
    "renewal_date": {
      "type": "string",
      "format": "date"
    },
    "return_url": {
      "type": "string",
      "format": "uri"
    },
    "reason": {
      "type": "string"
    }
  }
}
```

Example:

```json
{
  "reason": "Customer requested this change"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "status",
        "provider_subscription_id",
        "provider_customer_id",
        "customer"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "status": {
          "type": "string"
        },
        "subscription_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "customer_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "provider_subscription_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "provider_customer_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "customer": {
          "type": "object",
          "required": [
            "id",
            "email",
            "external_id",
            "name",
            "locale",
            "metadata"
          ],
          "properties": {
            "id": {
              "type": "integer"
            },
            "email": {
              "type": "string",
              "format": "email"
            },
            "external_id": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "locale": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
            },
            "metadata": {
              "type": "object",
              "maxProperties": 50,
              "additionalProperties": {
                "oneOf": [
                  {
                    "type": "string",
                    "maxLength": 500
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        },
        "product_variant_id": {
          "type": "integer"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 991,
    "status": "active",
    "subscription_id": "sub_example",
    "customer_id": "cus_maya",
    "provider_subscription_id": "sub_example",
    "provider_customer_id": "cus_maya",
    "customer": {
      "id": 314,
      "email": "maya.chen@example.com",
      "external_id": "crm_maya_314",
      "name": "Maya Chen",
      "locale": "en-GB",
      "metadata": {
        "plan": "standard",
        "seats": 3
      }
    },
    "product_variant_id": 84
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/customer-portal/subscriptions/{productSubscription}/actions/update-payment-method

Update payment method

Update payment method. Read capabilities first; state conflicts return 409.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.updateCustomerSubscriptionPaymentMethod({
  "productSubscription": 42,
  "reason": "Customer requested this change"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.update_customer_subscription_payment_method(
    product_subscription=42,
    reason="Customer requested this change"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->updateCustomerSubscriptionPaymentMethod(
    productSubscription: 42,
    reason: 'Customer requested this change',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    params := &sellapp.CustomerPortalUpdateSubscriptionPaymentMethodParams{}
    if err := json.Unmarshal([]byte("{\"reason\":\"Customer requested this change\"}"), params); err != nil { panic(err) }
    result, err := client.CustomerPortal().UpdateSubscriptionPaymentMethod(context.Background(), 42, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.UpdateSubscriptionPaymentMethodAsync(
    "42",
    new CustomerPortalUpdateSubscriptionPaymentMethodOptions
    {
        Reason = "Customer requested this change",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.updateSubscriptionPaymentMethod(productSubscription = "42", reason = "Customer requested this change")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.update_customer_subscription_payment_method(
  product_subscription: 42,
  reason: "Customer requested this change"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customer_portal::UpdateCustomerSubscriptionPaymentMethodParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let mut params = UpdateCustomerSubscriptionPaymentMethodParams::new(serde_json::from_str("{\"reason\":\"Customer requested this change\"}")?);
    let result = client.customer_portal().update_customer_subscription_payment_method("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.update_customer_subscription_payment_method(client, 42, %{"reason" => "Customer requested this change"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal update-customer-subscription-payment-method 42 --reason 'Customer requested this change' --yes

```

- Method: `POST`

- Path: `/v2/customer-portal/subscriptions/{productSubscription}/actions/update-payment-method`

- Full URL: `https://sell.app/api/v2/customer-portal/subscriptions/{productSubscription}/actions/update-payment-method`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_SUBSCRIPTION_ID='42'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/subscriptions/${SELLAPP_PRODUCT_SUBSCRIPTION_ID}/actions/update-payment-method" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}" \
  --header 'Idempotency-Key: project-library-2026-09-04' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "reason": "Customer requested this change"
}'
```

## Path Parameters
- `productSubscription` (`integer`, required): The productSubscription identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `Idempotency-Key` (`string`, required): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "preview_id": {
      "type": "string"
    },
    "product_variant_id": {
      "type": "integer"
    },
    "renewal_date": {
      "type": "string",
      "format": "date"
    },
    "return_url": {
      "type": "string",
      "format": "uri"
    },
    "reason": {
      "type": "string"
    }
  }
}
```

Example:

```json
{
  "reason": "Customer requested this change"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "status",
        "provider_subscription_id",
        "provider_customer_id",
        "customer"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "status": {
          "type": "string"
        },
        "subscription_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "customer_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "provider_subscription_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "provider_customer_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "customer": {
          "type": "object",
          "required": [
            "id",
            "email",
            "external_id",
            "name",
            "locale",
            "metadata"
          ],
          "properties": {
            "id": {
              "type": "integer"
            },
            "email": {
              "type": "string",
              "format": "email"
            },
            "external_id": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "locale": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
            },
            "metadata": {
              "type": "object",
              "maxProperties": 50,
              "additionalProperties": {
                "oneOf": [
                  {
                    "type": "string",
                    "maxLength": 500
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        },
        "product_variant_id": {
          "type": "integer"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 991,
    "status": "active",
    "subscription_id": "sub_example",
    "customer_id": "cus_maya",
    "provider_subscription_id": "sub_example",
    "provider_customer_id": "cus_maya",
    "customer": {
      "id": 314,
      "email": "maya.chen@example.com",
      "external_id": "crm_maya_314",
      "name": "Maya Chen",
      "locale": "en-GB",
      "metadata": {
        "plan": "standard",
        "seats": 3
      }
    },
    "product_variant_id": 84
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/customer-portal/subscriptions/{productSubscription}/actions/change-plan/preview

Preview a plan change

Preview a plan change. Read capabilities first; state conflicts return 409.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.previewCustomerSubscriptionPlanChange({
  "productSubscription": 42,
  "productVariantId": 84
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.preview_customer_subscription_plan_change(
    product_subscription=42,
    product_variant_id=84
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->previewCustomerSubscriptionPlanChange(
    productSubscription: 42,
    productVariantId: 84,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    params := &sellapp.CustomerPortalPreviewSubscriptionPlanChangeParams{}
    if err := json.Unmarshal([]byte("{\"product_variant_id\":84}"), params); err != nil { panic(err) }
    result, err := client.CustomerPortal().PreviewSubscriptionPlanChange(context.Background(), 42, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.PreviewSubscriptionPlanChangeAsync(
    "42",
    new CustomerPortalPreviewSubscriptionPlanChangeOptions
    {
        ProductVariantId = 84,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.previewSubscriptionPlanChange(productSubscription = "42", productVariantId = 84L)
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.preview_customer_subscription_plan_change(
  product_subscription: 42,
  product_variant_id: 84
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customer_portal::PreviewCustomerSubscriptionPlanChangeParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let mut params = PreviewCustomerSubscriptionPlanChangeParams::new(serde_json::from_str("{\"product_variant_id\":84}")?);
    let result = client.customer_portal().preview_customer_subscription_plan_change("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.preview_customer_subscription_plan_change(client, 42, %{"product_variant_id" => 84})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal preview-customer-subscription-plan-change 42 --product-variant-id 84 --yes

```

- Method: `POST`

- Path: `/v2/customer-portal/subscriptions/{productSubscription}/actions/change-plan/preview`

- Full URL: `https://sell.app/api/v2/customer-portal/subscriptions/{productSubscription}/actions/change-plan/preview`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_SUBSCRIPTION_ID='42'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/subscriptions/${SELLAPP_PRODUCT_SUBSCRIPTION_ID}/actions/change-plan/preview" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}" \
  --header 'Idempotency-Key: project-library-2026-09-04' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "product_variant_id": 84
}'
```

## Path Parameters
- `productSubscription` (`integer`, required): The productSubscription identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `Idempotency-Key` (`string`, required): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "preview_id": {
      "type": "string"
    },
    "product_variant_id": {
      "type": "integer"
    },
    "renewal_date": {
      "type": "string",
      "format": "date"
    },
    "return_url": {
      "type": "string",
      "format": "uri"
    },
    "reason": {
      "type": "string"
    }
  }
}
```

Example:

```json
{
  "product_variant_id": 84
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "status",
        "provider_subscription_id",
        "provider_customer_id",
        "customer"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "status": {
          "type": "string"
        },
        "subscription_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "customer_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "provider_subscription_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "provider_customer_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "customer": {
          "type": "object",
          "required": [
            "id",
            "email",
            "external_id",
            "name",
            "locale",
            "metadata"
          ],
          "properties": {
            "id": {
              "type": "integer"
            },
            "email": {
              "type": "string",
              "format": "email"
            },
            "external_id": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "locale": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
            },
            "metadata": {
              "type": "object",
              "maxProperties": 50,
              "additionalProperties": {
                "oneOf": [
                  {
                    "type": "string",
                    "maxLength": 500
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        },
        "product_variant_id": {
          "type": "integer"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 991,
    "status": "active",
    "subscription_id": "sub_example",
    "customer_id": "cus_maya",
    "provider_subscription_id": "sub_example",
    "provider_customer_id": "cus_maya",
    "customer": {
      "id": 314,
      "email": "maya.chen@example.com",
      "external_id": "crm_maya_314",
      "name": "Maya Chen",
      "locale": "en-GB",
      "metadata": {
        "plan": "standard",
        "seats": 3
      }
    },
    "product_variant_id": 84
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/customer-portal/subscriptions/{productSubscription}/actions/change-plan/confirm

Confirm a plan change

Confirm a plan change. Read capabilities first; state conflicts return 409.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.confirmCustomerSubscriptionPlanChange({
  "productSubscription": 42,
  "previewId": "preview_01K4"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.confirm_customer_subscription_plan_change(
    product_subscription=42,
    preview_id="preview_01K4"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->confirmCustomerSubscriptionPlanChange(
    productSubscription: 42,
    previewId: 'preview_01K4',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    params := &sellapp.CustomerPortalConfirmSubscriptionPlanChangeParams{}
    if err := json.Unmarshal([]byte("{\"preview_id\":\"preview_01K4\"}"), params); err != nil { panic(err) }
    result, err := client.CustomerPortal().ConfirmSubscriptionPlanChange(context.Background(), 42, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.ConfirmSubscriptionPlanChangeAsync(
    "42",
    new CustomerPortalConfirmSubscriptionPlanChangeOptions
    {
        PreviewId = "preview_01K4",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.confirmSubscriptionPlanChange(productSubscription = "42", previewId = "preview_01K4")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.confirm_customer_subscription_plan_change(
  product_subscription: 42,
  preview_id: "preview_01K4"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customer_portal::ConfirmCustomerSubscriptionPlanChangeParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let mut params = ConfirmCustomerSubscriptionPlanChangeParams::new(serde_json::from_str("{\"preview_id\":\"preview_01K4\"}")?);
    let result = client.customer_portal().confirm_customer_subscription_plan_change("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.confirm_customer_subscription_plan_change(client, 42, %{"preview_id" => "preview_01K4"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal confirm-customer-subscription-plan-change 42 --preview-id preview_01K4 --yes

```

- Method: `POST`

- Path: `/v2/customer-portal/subscriptions/{productSubscription}/actions/change-plan/confirm`

- Full URL: `https://sell.app/api/v2/customer-portal/subscriptions/{productSubscription}/actions/change-plan/confirm`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_SUBSCRIPTION_ID='42'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/subscriptions/${SELLAPP_PRODUCT_SUBSCRIPTION_ID}/actions/change-plan/confirm" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}" \
  --header 'Idempotency-Key: project-library-2026-09-04' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "preview_id": "preview_01K4"
}'
```

## Path Parameters
- `productSubscription` (`integer`, required): The productSubscription identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `Idempotency-Key` (`string`, required): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "preview_id": {
      "type": "string"
    },
    "product_variant_id": {
      "type": "integer"
    },
    "renewal_date": {
      "type": "string",
      "format": "date"
    },
    "return_url": {
      "type": "string",
      "format": "uri"
    },
    "reason": {
      "type": "string"
    }
  }
}
```

Example:

```json
{
  "preview_id": "preview_01K4"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "status",
        "provider_subscription_id",
        "provider_customer_id",
        "customer"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "status": {
          "type": "string"
        },
        "subscription_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "customer_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "provider_subscription_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "provider_customer_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "customer": {
          "type": "object",
          "required": [
            "id",
            "email",
            "external_id",
            "name",
            "locale",
            "metadata"
          ],
          "properties": {
            "id": {
              "type": "integer"
            },
            "email": {
              "type": "string",
              "format": "email"
            },
            "external_id": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "locale": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
            },
            "metadata": {
              "type": "object",
              "maxProperties": 50,
              "additionalProperties": {
                "oneOf": [
                  {
                    "type": "string",
                    "maxLength": 500
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        },
        "product_variant_id": {
          "type": "integer"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 991,
    "status": "active",
    "subscription_id": "sub_example",
    "customer_id": "cus_maya",
    "provider_subscription_id": "sub_example",
    "provider_customer_id": "cus_maya",
    "customer": {
      "id": 314,
      "email": "maya.chen@example.com",
      "external_id": "crm_maya_314",
      "name": "Maya Chen",
      "locale": "en-GB",
      "metadata": {
        "plan": "standard",
        "seats": 3
      }
    },
    "product_variant_id": 84
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/customer-portal/subscriptions/{productSubscription}/actions/change-renewal-date/preview

Preview a renewal-date change

Preview a renewal-date change. Read capabilities first; state conflicts return 409.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.previewCustomerSubscriptionRenewalDateChange({
  "productSubscription": 42,
  "renewalDate": "2026-10-15"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.preview_customer_subscription_renewal_date_change(
    product_subscription=42,
    renewal_date="2026-10-15"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->previewCustomerSubscriptionRenewalDateChange(
    productSubscription: 42,
    renewalDate: '2026-10-15',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    params := &sellapp.CustomerPortalPreviewSubscriptionRenewalDateChangeParams{}
    if err := json.Unmarshal([]byte("{\"renewal_date\":\"2026-10-15\"}"), params); err != nil { panic(err) }
    result, err := client.CustomerPortal().PreviewSubscriptionRenewalDateChange(context.Background(), 42, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.PreviewSubscriptionRenewalDateChangeAsync(
    "42",
    new CustomerPortalPreviewSubscriptionRenewalDateChangeOptions
    {
        RenewalDate = "2026-10-15",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.previewSubscriptionRenewalDateChange(productSubscription = "42", renewalDate = "2026-10-15")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.preview_customer_subscription_renewal_date_change(
  product_subscription: 42,
  renewal_date: "2026-10-15"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customer_portal::PreviewCustomerSubscriptionRenewalDateChangeParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let mut params = PreviewCustomerSubscriptionRenewalDateChangeParams::new(serde_json::from_str("{\"renewal_date\":\"2026-10-15\"}")?);
    let result = client.customer_portal().preview_customer_subscription_renewal_date_change("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.preview_customer_subscription_renewal_date_change(client, 42, %{"renewal_date" => "2026-10-15"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal preview-customer-subscription-renewal-date-change 42 --renewal-date 2026-10-15 --yes

```

- Method: `POST`

- Path: `/v2/customer-portal/subscriptions/{productSubscription}/actions/change-renewal-date/preview`

- Full URL: `https://sell.app/api/v2/customer-portal/subscriptions/{productSubscription}/actions/change-renewal-date/preview`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_SUBSCRIPTION_ID='42'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/subscriptions/${SELLAPP_PRODUCT_SUBSCRIPTION_ID}/actions/change-renewal-date/preview" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}" \
  --header 'Idempotency-Key: project-library-2026-09-04' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "renewal_date": "2026-10-15"
}'
```

## Path Parameters
- `productSubscription` (`integer`, required): The productSubscription identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `Idempotency-Key` (`string`, required): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "preview_id": {
      "type": "string"
    },
    "product_variant_id": {
      "type": "integer"
    },
    "renewal_date": {
      "type": "string",
      "format": "date"
    },
    "return_url": {
      "type": "string",
      "format": "uri"
    },
    "reason": {
      "type": "string"
    }
  }
}
```

Example:

```json
{
  "renewal_date": "2026-10-15"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "status",
        "provider_subscription_id",
        "provider_customer_id",
        "customer"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "status": {
          "type": "string"
        },
        "subscription_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "customer_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "provider_subscription_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "provider_customer_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "customer": {
          "type": "object",
          "required": [
            "id",
            "email",
            "external_id",
            "name",
            "locale",
            "metadata"
          ],
          "properties": {
            "id": {
              "type": "integer"
            },
            "email": {
              "type": "string",
              "format": "email"
            },
            "external_id": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "locale": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
            },
            "metadata": {
              "type": "object",
              "maxProperties": 50,
              "additionalProperties": {
                "oneOf": [
                  {
                    "type": "string",
                    "maxLength": 500
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        },
        "product_variant_id": {
          "type": "integer"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 991,
    "status": "active",
    "subscription_id": "sub_example",
    "customer_id": "cus_maya",
    "provider_subscription_id": "sub_example",
    "provider_customer_id": "cus_maya",
    "customer": {
      "id": 314,
      "email": "maya.chen@example.com",
      "external_id": "crm_maya_314",
      "name": "Maya Chen",
      "locale": "en-GB",
      "metadata": {
        "plan": "standard",
        "seats": 3
      }
    },
    "product_variant_id": 84
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/customer-portal/subscriptions/{productSubscription}/actions/change-renewal-date/confirm

Confirm a renewal-date change

Confirm a renewal-date change. Read capabilities first; state conflicts return 409.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  customerSession: process.env.SELLAPP_CUSTOMER_SESSION!,
  store: "",
});

const result = await client.customerPortal.confirmCustomerSubscriptionRenewalDateChange({
  "productSubscription": 42,
  "previewId": "preview_01K4"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], customer_session=os.environ["SELLAPP_CUSTOMER_SESSION"], store="")

result = client.customer_portal.confirm_customer_subscription_renewal_date_change(
    product_subscription=42,
    preview_id="preview_01K4"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    customerSession: getenv('SELLAPP_CUSTOMER_SESSION'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: "",
);

$result = $client->customerPortal()->confirmCustomerSubscriptionRenewalDateChange(
    productSubscription: 42,
    previewId: 'preview_01K4',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient("", "", sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")), sellapp.WithCustomerSession(os.Getenv("SELLAPP_CUSTOMER_SESSION")))
    params := &sellapp.CustomerPortalConfirmSubscriptionRenewalDateChangeParams{}
    if err := json.Unmarshal([]byte("{\"preview_id\":\"preview_01K4\"}"), params); err != nil { panic(err) }
    result, err := client.CustomerPortal().ConfirmSubscriptionRenewalDateChange(context.Background(), 42, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    CustomerSession = Environment.GetEnvironmentVariable("SELLAPP_CUSTOMER_SESSION"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = "",
});

var result = await client.CustomerPortal.ConfirmSubscriptionRenewalDateChangeAsync(
    "42",
    new CustomerPortalConfirmSubscriptionRenewalDateChangeOptions
    {
        PreviewId = "preview_01K4",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), customerSession = System.getenv("SELLAPP_CUSTOMER_SESSION"), store = "")
    val result = client.customerPortal.confirmSubscriptionRenewalDateChange(productSubscription = "42", previewId = "preview_01K4")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), customer_session: ENV.fetch("SELLAPP_CUSTOMER_SESSION"), store: "")

result = client.customer_portal.confirm_customer_subscription_renewal_date_change(
  product_subscription: 42,
  preview_id: "preview_01K4"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customer_portal::ConfirmCustomerSubscriptionRenewalDateChangeParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("", "").with_base_url(std::env::var("SELLAPP_API_BASE_URL")?).with_customer_session(std::env::var("SELLAPP_CUSTOMER_SESSION")?);
    let mut params = ConfirmCustomerSubscriptionRenewalDateChangeParams::new(serde_json::from_str("{\"preview_id\":\"preview_01K4\"}")?);
    let result = client.customer_portal().confirm_customer_subscription_renewal_date_change("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  customer_session: System.fetch_env!("SELLAPP_CUSTOMER_SESSION"),
  store: ""
)

{:ok, result} = SellApp.CustomerPortal.confirm_customer_subscription_renewal_date_change(client, 42, %{"preview_id" => "preview_01K4"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-portal confirm-customer-subscription-renewal-date-change 42 --preview-id preview_01K4 --yes

```

- Method: `POST`

- Path: `/v2/customer-portal/subscriptions/{productSubscription}/actions/change-renewal-date/confirm`

- Full URL: `https://sell.app/api/v2/customer-portal/subscriptions/{productSubscription}/actions/change-renewal-date/confirm`

- Authentication: `Authorization: Bearer <credential>` header required

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_PRODUCT_SUBSCRIPTION_ID='42'
export SELLAPP_CUSTOMER_SESSION_TOKEN='replace-me'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-portal/subscriptions/${SELLAPP_PRODUCT_SUBSCRIPTION_ID}/actions/change-renewal-date/confirm" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_CUSTOMER_SESSION_TOKEN}" \
  --header 'Idempotency-Key: project-library-2026-09-04' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "preview_id": "preview_01K4"
}'
```

## Path Parameters
- `productSubscription` (`integer`, required): The productSubscription identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, required): Use Bearer followed by the credential. See authentication alternatives above.
- `Idempotency-Key` (`string`, required): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "preview_id": {
      "type": "string"
    },
    "product_variant_id": {
      "type": "integer"
    },
    "renewal_date": {
      "type": "string",
      "format": "date"
    },
    "return_url": {
      "type": "string",
      "format": "uri"
    },
    "reason": {
      "type": "string"
    }
  }
}
```

Example:

```json
{
  "preview_id": "preview_01K4"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "status",
        "provider_subscription_id",
        "provider_customer_id",
        "customer"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "status": {
          "type": "string"
        },
        "subscription_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "customer_id": {
          "type": [
            "string",
            "null"
          ],
          "deprecated": true
        },
        "provider_subscription_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "provider_customer_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "customer": {
          "type": "object",
          "required": [
            "id",
            "email",
            "external_id",
            "name",
            "locale",
            "metadata"
          ],
          "properties": {
            "id": {
              "type": "integer"
            },
            "email": {
              "type": "string",
              "format": "email"
            },
            "external_id": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "name": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "locale": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
            },
            "metadata": {
              "type": "object",
              "maxProperties": 50,
              "additionalProperties": {
                "oneOf": [
                  {
                    "type": "string",
                    "maxLength": 500
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        },
        "product_variant_id": {
          "type": "integer"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 991,
    "status": "active",
    "subscription_id": "sub_example",
    "customer_id": "cus_maya",
    "provider_subscription_id": "sub_example",
    "provider_customer_id": "cus_maya",
    "customer": {
      "id": 314,
      "email": "maya.chen@example.com",
      "external_id": "crm_maya_314",
      "name": "Maya Chen",
      "locale": "en-GB",
      "metadata": {
        "plan": "standard",
        "seats": 3
      }
    },
    "product_variant_id": 84
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Customer sessions (/docs/api/customer-sessions)

Choose exactly one customer identifier. SellApp returns a 15-minute bearer token and a separate, single-use hosted redemption URL. Both plaintext credentials appear once, so store neither in logs and do not retry creation expecting a replay.

## POST /v2/customer-sessions

Create a customer session

Return a 15-minute bearer token once plus a separate single-use hosted redemption URL. This response is never cached or replayed. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.customerSessions.createCustomerSession({
  "externalCustomerId": "crm_maya_314"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.customer_sessions.create_customer_session(body={"external_customer_id": "crm_maya_314"})
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->customerSessions()->createCustomerSession(body: ['external_customer_id' => 'crm_maya_314']);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CustomerSessionsCreateParams{}
    if err := json.Unmarshal([]byte("{\"external_customer_id\":\"crm_maya_314\"}"), &params.Body); err != nil { panic(err) }
    result, err := client.CustomerSessions().Create(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CustomerSessions.CreateAsync(new CustomerSessionsCreateOptions { Body = JsonConvert.DeserializeObject<CreateCustomerSessionRequestApplicationJsonOneOfValue2>("{\"external_customer_id\":\"crm_maya_314\"}")! });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.customerSessions.create(requestBody = mapOf("external_customer_id" to "crm_maya_314"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.customer_sessions.create_customer_session(external_customer_id: "crm_maya_314")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customer_sessions::CreateCustomerSessionParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateCustomerSessionParams::new(serde_json::from_str("{\"external_customer_id\":\"crm_maya_314\"}")?);
    let result = client.customer_sessions().create_customer_session(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CustomerSessions.create_customer_session(client, %{"external_customer_id" => "crm_maya_314"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-sessions create-customer-session --external-customer-id crm_maya_314 --yes

```

- Method: `POST`

- Path: `/v2/customer-sessions`

- Full URL: `https://sell.app/api/v2/customer-sessions`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-sessions" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "external_customer_id": "crm_maya_314"
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "oneOf": [
    {
      "type": "object",
      "required": [
        "customer_id"
      ],
      "properties": {
        "customer_id": {
          "type": "integer"
        }
      },
      "additionalProperties": false
    },
    {
      "type": "object",
      "required": [
        "external_customer_id"
      ],
      "properties": {
        "external_customer_id": {
          "type": "string"
        }
      },
      "additionalProperties": false
    }
  ]
}
```

Example:

```json
{
  "external_customer_id": "crm_maya_314"
}
```

## Responses

### 201

Created.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "token",
        "redemption_url",
        "expires_at"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "token": {
          "type": "string",
          "writeOnly": true
        },
        "redemption_url": {
          "type": "string",
          "format": "uri",
          "writeOnly": true
        },
        "expires_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": "01992b45-cc84-7cc6-a331-67be817ed51b",
    "token": "cs_once_redacted",
    "redemption_url": "https://sell.app/customer/session/redeem/once_redacted",
    "expires_at": "2026-09-04T10:15:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## DELETE /v2/customer-sessions/{session}

Revoke a customer session

Revoke immediately. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.customerSessions.revokeCustomerSession({
  "session": "session_01K4CUSTOMER"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.customer_sessions.revoke_customer_session(session="session_01K4CUSTOMER")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->customerSessions()->revokeCustomerSession(session: 'session_01K4CUSTOMER');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    if err := client.CustomerSessions().Revoke(context.Background(), "session_01K4CUSTOMER"); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.CustomerSessions.RevokeAsync("session_01K4CUSTOMER");
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.customerSessions.revoke(session = "session_01K4CUSTOMER")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.customer_sessions.revoke_customer_session(session: "session_01K4CUSTOMER")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customer_sessions::RevokeCustomerSessionParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = RevokeCustomerSessionParams::default();
    let result = client.customer_sessions().revoke_customer_session("session_01K4CUSTOMER", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CustomerSessions.revoke_customer_session(client, "session_01K4CUSTOMER")
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customer-sessions revoke-customer-session session_01K4CUSTOMER --yes

```

- Method: `DELETE`

- Path: `/v2/customer-sessions/{session}`

- Full URL: `https://sell.app/api/v2/customer-sessions/{session}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_SESSION_ID='session_01K4CUSTOMER'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v2/customer-sessions/${SELLAPP_SESSION_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `session` (`string`, required): The session identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "revoked"
  ],
  "properties": {
    "revoked": {
      "type": "boolean"
    }
  }
}
```

Example:

```json
{
  "revoked": true
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Create a credits product (/docs/api/credits/create-a-credit-product)

## POST /v2/credit-products

Create a credits product

Create a credits product with one default CREDITS variant. Published products require at least one ordered, non-overlapping rate tier. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.creditsProducts.create({
  "title": "Design credits",
  "visibility": "HIDDEN",
  "priceCents": 1999,
  "currency": "USD"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.credits_products.create(
    title="Design credits",
    visibility="HIDDEN",
    price_cents=1999,
    currency="USD"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->creditsProducts()->create(
    title: 'Design credits',
    visibility: 'HIDDEN',
    priceCents: 1999,
    currency: 'USD',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CreditsProductsCreateParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Design credits\",\"visibility\":\"HIDDEN\",\"price_cents\":1999,\"currency\":\"USD\"}"), params); err != nil { panic(err) }
    result, err := client.CreditsProducts().Create(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CreditsProducts.CreateAsync(new CreditsProductsCreateOptions
    {
        Title = "Design credits",
        Visibility = JsonConvert.DeserializeObject<CatalogVisibility>("\"HIDDEN\"")!,
        PriceCents = 1999,
        Currency = "USD",
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.creditsProducts.create(title = "Design credits", visibility = app.sell.sellapp.types.CatalogVisibility("HIDDEN"), priceCents = 1999L, currency = "USD")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.credits_products.create(
  title: "Design credits",
  visibility: "HIDDEN",
  price_cents: 1999,
  currency: "USD"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::credits_products::CreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateParams::new(serde_json::from_str("{\"title\":\"Design credits\",\"visibility\":\"HIDDEN\",\"price_cents\":1999,\"currency\":\"USD\"}")?);
    let result = client.credits_products().create(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CreditsProducts.create(client, %{"title" => "Design credits", "visibility" => "HIDDEN", "price_cents" => 1999, "currency" => "USD"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp credits products create --title 'Design credits' --visibility HIDDEN --price-cents 1999 --currency USD --yes

```

- Method: `POST`

- Path: `/v2/credit-products`

- Full URL: `https://sell.app/api/v2/credit-products`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/credit-products" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Design credits",
  "visibility": "HIDDEN",
  "price_cents": 1999,
  "currency": "USD"
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255
    },
    "slug": {
      "type": "string",
      "maxLength": 255,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
    },
    "description": {
      "type": [
        "string",
        "null"
      ],
      "minLength": 5,
      "maxLength": 5000
    },
    "visibility": {
      "type": "string",
      "enum": [
        "PUBLIC",
        "ON_HOLD",
        "HIDDEN",
        "PRIVATE"
      ]
    },
    "section_id": {
      "type": [
        "integer",
        "null"
      ]
    },
    "is_draft": {
      "type": "boolean",
      "default": true
    },
    "price_cents": {
      "type": "integer",
      "minimum": 0,
      "description": "Base price in integer minor currency units."
    },
    "currency": {
      "type": "string",
      "minLength": 3,
      "maxLength": 3,
      "example": "USD"
    },
    "minimum_purchase_quantity": {
      "type": "integer",
      "minimum": 1,
      "maximum": 2147483647
    },
    "maximum_purchase_quantity": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1,
      "maximum": 2147483647
    },
    "quantity_increment": {
      "type": "integer",
      "minimum": 1
    },
    "stock": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 0,
      "maximum": 2147483647
    },
    "payment_methods": {
      "type": "array",
      "uniqueItems": true,
      "items": {
        "type": "string",
        "enum": [
          "AUTHNET",
          "BTCPAY",
          "CASHAPP",
          "COINBASE",
          "PADDLE",
          "PAYDASH",
          "PAYPAL",
          "PAYSTACK",
          "SQUARE",
          "STRIPE",
          "VENMO",
          "NMI",
          "MERCADO_PAGO",
          "MOLLIE",
          "RAZORPAY",
          "CUSTOM_PAYMENT_METHOD",
          "LIFI",
          "BTC",
          "LTC",
          "ETH",
          "XMR",
          "SOL",
          "ADA",
          "BNB",
          "TRX",
          "MATIC",
          "ETH_USDT",
          "ETH_USDC",
          "ETH_UNI",
          "ETH_SHIB",
          "ETH_DAI",
          "BNB_USDT",
          "BNB_USDC",
          "TRX_USDT",
          "TRX_USDC",
          "SOL_USDT",
          "SOL_USDC"
        ]
      }
    },
    "rate_tiers": {
      "type": "array",
      "maxItems": 100,
      "items": {
        "type": "object",
        "required": [
          "min_quantity",
          "max_quantity",
          "unit_price"
        ],
        "properties": {
          "min_quantity": {
            "type": "integer",
            "minimum": 1,
            "example": 100
          },
          "max_quantity": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "example": 999
          },
          "unit_price": {
            "type": "string",
            "maxLength": 32,
            "pattern": "^\\d+(?:\\.\\d{1,4})?$",
            "description": "Positive per-credit price as a decimal string with at most four decimal places. Numeric floats and zero are not accepted.",
            "example": "0.5000"
          }
        }
      }
    },
    "expected_updated_at": {
      "type": "string",
      "format": "date-time"
    }
  },
  "required": [
    "title",
    "visibility"
  ]
}
```

Example (minimal):

```json
{
  "title": "Design credits",
  "visibility": "HIDDEN",
  "price_cents": 1999,
  "currency": "USD"
}
```

## Responses

### 201

Credits product created.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "store_id",
        "title",
        "slug",
        "visibility",
        "type",
        "is_draft",
        "is_discoverable",
        "default_variant"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "store_id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ]
        },
        "type": {
          "type": "string",
          "const": "credits"
        },
        "is_draft": {
          "type": "boolean"
        },
        "is_discoverable": {
          "type": "boolean"
        },
        "section_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "default_variant": {
          "anyOf": [
            {
              "type": "object",
              "description": "The single sellable variant, or null when zero or multiple variants exist. When null, variant_invariant explains the issue.",
              "required": [
                "id",
                "price_cents",
                "currency",
                "minimum_purchase_quantity",
                "quantity_increment",
                "payment_methods",
                "rate_tiers"
              ],
              "properties": {
                "id": {
                  "type": "integer"
                },
                "price_cents": {
                  "type": "integer",
                  "minimum": 0
                },
                "currency": {
                  "type": "string"
                },
                "minimum_purchase_quantity": {
                  "type": "integer",
                  "minimum": 1
                },
                "maximum_purchase_quantity": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "quantity_increment": {
                  "type": "integer",
                  "minimum": 1
                },
                "stock": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                },
                "payment_methods": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "rate_tiers": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "min_quantity",
                      "max_quantity",
                      "unit_price"
                    ],
                    "properties": {
                      "min_quantity": {
                        "type": "integer",
                        "minimum": 1,
                        "example": 100
                      },
                      "max_quantity": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 1,
                        "example": 999
                      },
                      "unit_price": {
                        "type": "string",
                        "maxLength": 32,
                        "pattern": "^\\d+(?:\\.\\d{1,4})?$",
                        "description": "Positive per-credit price as a decimal string with at most four decimal places. Numeric floats and zero are not accepted.",
                        "example": "0.5000"
                      }
                    }
                  }
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "variant_invariant": {
          "type": "object",
          "description": "Present only when default_variant is null. Inspect the state before attempting a purchase.",
          "required": [
            "state",
            "variant_count"
          ],
          "properties": {
            "state": {
              "type": "string",
              "enum": [
                "missing_default_variant",
                "multiple_default_variants"
              ]
            },
            "variant_count": {
              "type": "integer",
              "minimum": 0
            }
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 121,
    "store_id": 1,
    "title": "Design credits",
    "slug": "design-credits",
    "description": "Credits for future design work.",
    "visibility": "HIDDEN",
    "type": "credits",
    "is_draft": false,
    "is_discoverable": false,
    "section_id": null,
    "default_variant": {
      "id": 4322,
      "price_cents": 50,
      "currency": "USD",
      "minimum_purchase_quantity": 1,
      "maximum_purchase_quantity": null,
      "quantity_increment": 1,
      "stock": null,
      "payment_methods": [
        "STRIPE"
      ],
      "rate_tiers": []
    },
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z",
    "deleted_at": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Delete a credits product (/docs/api/credits/delete-a-credit-product)

## DELETE /v2/credit-products/{creditProduct}

Delete a credits product

Soft-delete a store-scoped credits product. Optional expected_updated_at protects against stale writes (422). Active subscriptions, any credit balance history, or pending purchase fulfillment prevent deletion (422). OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.creditsProducts.delete({
  "creditProduct": 1,
  "expectedUpdatedAt": new Date("2026-08-24T10:00:00.000000Z")
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.credits_products.delete(
    credit_product=1,
    expected_updated_at="2026-08-24T10:00:00.000000Z"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->creditsProducts()->delete(
    creditProduct: 1,
    expectedUpdatedAt: '2026-08-24T10:00:00.000000Z',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CreditsProductsDeleteParams{}
    if err := json.Unmarshal([]byte("{\"expected_updated_at\":\"2026-08-24T10:00:00.000000Z\"}"), params); err != nil { panic(err) }
    if err := client.CreditsProducts().Delete(context.Background(), 1, params); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.CreditsProducts.DeleteAsync(
    "1",
    new CreditsProductsDeleteOptions
    {
        ExpectedUpdatedAt = JsonConvert.DeserializeObject<DateTimeOffset>("\"2026-08-24T10:00:00.000000Z\"")!,
    }
);
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.creditsProducts.delete(creditProduct = "1", expectedUpdatedAt = java.time.OffsetDateTime.parse("2026-08-24T10:00:00.000000Z"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.credits_products.delete(
  credit_product: 1,
  expected_updated_at: "2026-08-24T10:00:00.000000Z"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::credits_products::DeleteParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = DeleteParams::new(serde_json::from_str("{\"expected_updated_at\":\"2026-08-24T10:00:00.000000Z\"}")?);
    let result = client.credits_products().delete("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CreditsProducts.delete(client, 1, %{"expected_updated_at" => "2026-08-24T10:00:00.000000Z"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp credits products delete 1 --expected-updated-at 2026-08-24T10:00:00.000000Z --yes

```

- Method: `DELETE`

- Path: `/v2/credit-products/{creditProduct}`

- Full URL: `https://sell.app/api/v2/credit-products/{creditProduct}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CREDIT_PRODUCT_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v2/credit-products/${SELLAPP_CREDIT_PRODUCT_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "expected_updated_at": "2026-08-24T10:00:00.000000Z"
}'
```

## Path Parameters
- `creditProduct` (`integer`, required): The creditProduct path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "expected_updated_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
```

Example:

```json
{
  "expected_updated_at": "2026-08-24T10:00:00.000000Z"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "store_id",
        "title",
        "slug",
        "visibility",
        "type",
        "is_draft",
        "is_discoverable",
        "default_variant"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "store_id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ]
        },
        "type": {
          "type": "string",
          "const": "credits"
        },
        "is_draft": {
          "type": "boolean"
        },
        "is_discoverable": {
          "type": "boolean"
        },
        "section_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "default_variant": {
          "anyOf": [
            {
              "type": "object",
              "description": "The single sellable variant, or null when zero or multiple variants exist. When null, variant_invariant explains the issue.",
              "required": [
                "id",
                "price_cents",
                "currency",
                "minimum_purchase_quantity",
                "quantity_increment",
                "payment_methods",
                "rate_tiers"
              ],
              "properties": {
                "id": {
                  "type": "integer"
                },
                "price_cents": {
                  "type": "integer",
                  "minimum": 0
                },
                "currency": {
                  "type": "string"
                },
                "minimum_purchase_quantity": {
                  "type": "integer",
                  "minimum": 1
                },
                "maximum_purchase_quantity": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "quantity_increment": {
                  "type": "integer",
                  "minimum": 1
                },
                "stock": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                },
                "payment_methods": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "rate_tiers": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "min_quantity",
                      "max_quantity",
                      "unit_price"
                    ],
                    "properties": {
                      "min_quantity": {
                        "type": "integer",
                        "minimum": 1,
                        "example": 100
                      },
                      "max_quantity": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 1,
                        "example": 999
                      },
                      "unit_price": {
                        "type": "string",
                        "maxLength": 32,
                        "pattern": "^\\d+(?:\\.\\d{1,4})?$",
                        "description": "Positive per-credit price as a decimal string with at most four decimal places. Numeric floats and zero are not accepted.",
                        "example": "0.5000"
                      }
                    }
                  }
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "variant_invariant": {
          "type": "object",
          "description": "Present only when default_variant is null. Inspect the state before attempting a purchase.",
          "required": [
            "state",
            "variant_count"
          ],
          "properties": {
            "state": {
              "type": "string",
              "enum": [
                "missing_default_variant",
                "multiple_default_variants"
              ]
            },
            "variant_count": {
              "type": "integer",
              "minimum": 0
            }
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 121,
    "store_id": 1,
    "title": "Design credits",
    "slug": "design-credits",
    "description": "Credits for future design work.",
    "visibility": "HIDDEN",
    "type": "credits",
    "is_draft": false,
    "is_discoverable": false,
    "section_id": null,
    "default_variant": {
      "id": 4322,
      "price_cents": 50,
      "currency": "USD",
      "minimum_purchase_quantity": 1,
      "maximum_purchase_quantity": null,
      "quantity_increment": 1,
      "stock": null,
      "payment_methods": [
        "STRIPE"
      ],
      "rate_tiers": []
    },
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z",
    "deleted_at": "2026-09-07T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Overview (/docs/api/credits)



Credits products sell integer usage units such as API calls, AI tokens, or game currency. Each dedicated credits product owns exactly one default `CREDITS` variant and can define ordered, non-overlapping rate tiers.

Each balance belongs to one store, customer, and credits product. Adding, spending, or adjusting credits updates the balance and adds a permanent transaction record together. Supply an `idempotency_key` for every transaction: retrying identical input returns the existing entry; reusing the key for different input is rejected.

All credit quantities and balances are integers. Base prices use integer minor currency units in `price_cents`. Exact tier unit prices remain decimal strings with at most four decimal places and must never be sent as JSON floats.

For API keys, product endpoints require the `listing` ability; balance and transaction endpoints require the `credit` ability. OAuth uses `products:read` or `products:write` for product endpoints and `payments:read` or `payments:write` for balances and transactions. The account's current store permissions also apply.

## Endpoints [#endpoints]

* [List credits products](/api/credits/list-credit-products)
* [Search credits products](/api/credits/search-credit-products)
* [Create a credits product](/api/credits/create-a-credit-product)
* [Retrieve a credits product](/api/credits/retrieve-a-credit-product)
* [Update a credits product](/api/credits/update-a-credit-product)
* [Replace a credits product](/api/credits/replace-a-credit-product)
* [Delete a credits product](/api/credits/delete-a-credit-product)
* [List credit balances](/api/credits/list-credit-balances)
* [Retrieve a credit balance](/api/credits/retrieve-a-credit-balance)
* [Record a credit transaction](/api/credits/record-a-credit-transaction)


# List credit balances (/docs/api/credits/list-credit-balances)

## GET /v2/credit-balances

List credit balances

List store-scoped customer balances for dedicated credits products. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.creditsBalances.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.credits_balances.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->creditsBalances()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CreditsBalancesListParams{}
    page := client.CreditsBalances().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CreditsBalances.ListAsync(new CreditsBalancesListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.creditsBalances.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.credits_balances.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::credits_balances::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.credits_balances().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CreditsBalances.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp credits balances list

```

- Method: `GET`

- Path: `/v2/credit-balances`

- Full URL: `https://sell.app/api/v2/credit-balances`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/credit-balances" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching items in one data array without pagination links or metadata.
- `customer_id` (`integer`, optional): Filter by a store customer ID.
- `product_id` (`integer`, optional): Filter by a credits product ID.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "id",
              "store_id",
              "customer_id",
              "product_id",
              "balance_units"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "store_id": {
                "type": "integer"
              },
              "customer_id": {
                "type": "integer"
              },
              "customer_email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email",
                "description": "The email of the customer holding the balance, or null once the customer is deleted."
              },
              "product_id": {
                "type": "integer"
              },
              "product_title": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The title of the credits product, or null once the product is soft-deleted."
              },
              "balance_units": {
                "type": "integer",
                "minimum": 0
              },
              "ledger_entries": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "id",
                    "store_id",
                    "customer_id",
                    "product_id",
                    "kind",
                    "amount_units",
                    "balance_after_units",
                    "idempotency_key"
                  ],
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "store_id": {
                      "type": "integer"
                    },
                    "customer_id": {
                      "type": "integer"
                    },
                    "product_id": {
                      "type": "integer"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "grant",
                        "consumption",
                        "adjustment"
                      ]
                    },
                    "amount_units": {
                      "type": "integer"
                    },
                    "balance_after_units": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "idempotency_key": {
                      "type": "string",
                      "maxLength": 128
                    },
                    "source_type": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "source_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "metadata": {
                      "anyOf": [
                        {
                          "type": "object",
                          "additionalProperties": true
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "actor_user_id": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "id",
              "store_id",
              "customer_id",
              "product_id",
              "balance_units"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "store_id": {
                "type": "integer"
              },
              "customer_id": {
                "type": "integer"
              },
              "customer_email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email",
                "description": "The email of the customer holding the balance, or null once the customer is deleted."
              },
              "product_id": {
                "type": "integer"
              },
              "product_title": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The title of the credits product, or null once the product is soft-deleted."
              },
              "balance_units": {
                "type": "integer",
                "minimum": 0
              },
              "ledger_entries": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "id",
                    "store_id",
                    "customer_id",
                    "product_id",
                    "kind",
                    "amount_units",
                    "balance_after_units",
                    "idempotency_key"
                  ],
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "store_id": {
                      "type": "integer"
                    },
                    "customer_id": {
                      "type": "integer"
                    },
                    "product_id": {
                      "type": "integer"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "grant",
                        "consumption",
                        "adjustment"
                      ]
                    },
                    "amount_units": {
                      "type": "integer"
                    },
                    "balance_after_units": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "idempotency_key": {
                      "type": "string",
                      "maxLength": 128
                    },
                    "source_type": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "source_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "metadata": {
                      "anyOf": [
                        {
                          "type": "object",
                          "additionalProperties": true
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "actor_user_id": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example (minimal):

```json
{
  "data": [
    {
      "id": 81,
      "store_id": 1,
      "customer_id": 77,
      "customer_email": "maya@example.com",
      "product_id": 121,
      "product_title": "Design credits",
      "balance_units": 0,
      "ledger_entries": [],
      "created_at": "2026-09-01T12:00:00Z",
      "updated_at": "2026-09-01T12:00:00Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/credit-balances?page=1",
    "last": "https://sell.app/api/v2/credit-balances?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/credit-balances?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ],
    "path": "https://sell.app/api/v2/credit-balances",
    "per_page": 15,
    "to": 1,
    "total": 1
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# List credits products (/docs/api/credits/list-credit-products)

## GET /v2/credit-products

List credits products

List dedicated credits products and their single default variants. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.creditsProducts.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.credits_products.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->creditsProducts()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CreditsProductsListParams{}
    page := client.CreditsProducts().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CreditsProducts.ListAsync(new CreditsProductsListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.creditsProducts.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.credits_products.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::credits_products::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.credits_products().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CreditsProducts.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp credits products list

```

- Method: `GET`

- Path: `/v2/credit-products`

- Full URL: `https://sell.app/api/v2/credit-products`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/credit-products" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching items in one data array without pagination links or metadata.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "id",
              "store_id",
              "title",
              "slug",
              "visibility",
              "type",
              "is_draft",
              "is_discoverable",
              "default_variant"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "store_id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ]
              },
              "type": {
                "type": "string",
                "const": "credits"
              },
              "is_draft": {
                "type": "boolean"
              },
              "is_discoverable": {
                "type": "boolean"
              },
              "section_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "default_variant": {
                "anyOf": [
                  {
                    "type": "object",
                    "description": "The single sellable variant, or null when zero or multiple variants exist. When null, variant_invariant explains the issue.",
                    "required": [
                      "id",
                      "price_cents",
                      "currency",
                      "minimum_purchase_quantity",
                      "quantity_increment",
                      "payment_methods",
                      "rate_tiers"
                    ],
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "price_cents": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "currency": {
                        "type": "string"
                      },
                      "minimum_purchase_quantity": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "maximum_purchase_quantity": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "quantity_increment": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "stock": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 0
                      },
                      "payment_methods": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "rate_tiers": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "required": [
                            "min_quantity",
                            "max_quantity",
                            "unit_price"
                          ],
                          "properties": {
                            "min_quantity": {
                              "type": "integer",
                              "minimum": 1,
                              "example": 100
                            },
                            "max_quantity": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 1,
                              "example": 999
                            },
                            "unit_price": {
                              "type": "string",
                              "maxLength": 32,
                              "pattern": "^\\d+(?:\\.\\d{1,4})?$",
                              "description": "Positive per-credit price as a decimal string with at most four decimal places. Numeric floats and zero are not accepted.",
                              "example": "0.5000"
                            }
                          }
                        }
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "variant_invariant": {
                "type": "object",
                "description": "Present only when default_variant is null. Inspect the state before attempting a purchase.",
                "required": [
                  "state",
                  "variant_count"
                ],
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "missing_default_variant",
                      "multiple_default_variants"
                    ]
                  },
                  "variant_count": {
                    "type": "integer",
                    "minimum": 0
                  }
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "id",
              "store_id",
              "title",
              "slug",
              "visibility",
              "type",
              "is_draft",
              "is_discoverable",
              "default_variant"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "store_id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ]
              },
              "type": {
                "type": "string",
                "const": "credits"
              },
              "is_draft": {
                "type": "boolean"
              },
              "is_discoverable": {
                "type": "boolean"
              },
              "section_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "default_variant": {
                "anyOf": [
                  {
                    "type": "object",
                    "description": "The single sellable variant, or null when zero or multiple variants exist. When null, variant_invariant explains the issue.",
                    "required": [
                      "id",
                      "price_cents",
                      "currency",
                      "minimum_purchase_quantity",
                      "quantity_increment",
                      "payment_methods",
                      "rate_tiers"
                    ],
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "price_cents": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "currency": {
                        "type": "string"
                      },
                      "minimum_purchase_quantity": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "maximum_purchase_quantity": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "quantity_increment": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "stock": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 0
                      },
                      "payment_methods": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "rate_tiers": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "required": [
                            "min_quantity",
                            "max_quantity",
                            "unit_price"
                          ],
                          "properties": {
                            "min_quantity": {
                              "type": "integer",
                              "minimum": 1,
                              "example": 100
                            },
                            "max_quantity": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 1,
                              "example": 999
                            },
                            "unit_price": {
                              "type": "string",
                              "maxLength": 32,
                              "pattern": "^\\d+(?:\\.\\d{1,4})?$",
                              "description": "Positive per-credit price as a decimal string with at most four decimal places. Numeric floats and zero are not accepted.",
                              "example": "0.5000"
                            }
                          }
                        }
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "variant_invariant": {
                "type": "object",
                "description": "Present only when default_variant is null. Inspect the state before attempting a purchase.",
                "required": [
                  "state",
                  "variant_count"
                ],
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "missing_default_variant",
                      "multiple_default_variants"
                    ]
                  },
                  "variant_count": {
                    "type": "integer",
                    "minimum": 0
                  }
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example (minimal):

```json
{
  "data": [
    {
      "id": 121,
      "store_id": 1,
      "title": "Design credits",
      "slug": "design-credits",
      "description": "Credits for future design work.",
      "visibility": "HIDDEN",
      "type": "credits",
      "is_draft": false,
      "is_discoverable": false,
      "section_id": null,
      "default_variant": {
        "id": 4322,
        "price_cents": 50,
        "currency": "USD",
        "minimum_purchase_quantity": 1,
        "maximum_purchase_quantity": null,
        "quantity_increment": 1,
        "stock": null,
        "payment_methods": [
          "STRIPE"
        ],
        "rate_tiers": []
      },
      "created_at": "2026-09-01T12:00:00Z",
      "updated_at": "2026-09-01T12:00:00Z",
      "deleted_at": null
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/credit-products?page=1",
    "last": "https://sell.app/api/v2/credit-products?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/credit-products?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ],
    "path": "https://sell.app/api/v2/credit-products",
    "per_page": 15,
    "to": 1,
    "total": 1
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Record a credit transaction (/docs/api/credits/record-a-credit-transaction)

## POST /v2/credit-transactions

Record a credit transaction

Atomically grant, consume, or administratively adjust integer credit units. Reusing the same idempotency key with the same transaction is a no-op; conflicting reuse is rejected. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.credits.record({
  "customerId": 125,
  "productId": 120,
  "kind": "grant",
  "amountUnits": 1000,
  "idempotencyKey": "credits-grant-01992a65",
  "reason": "Launch cohort allocation"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.credits.record(
    customer_id=125,
    product_id=120,
    kind="grant",
    amount_units=1000,
    idempotency_key="credits-grant-01992a65",
    reason="Launch cohort allocation"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->credits()->record(
    customerId: 125,
    productId: 120,
    kind: 'grant',
    amountUnits: 1000,
    idempotencyKey: 'credits-grant-01992a65',
    reason: 'Launch cohort allocation',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CreditsRecordParams{}
    if err := json.Unmarshal([]byte("{\"customer_id\":125,\"product_id\":120,\"kind\":\"grant\",\"amount_units\":1000,\"idempotency_key\":\"credits-grant-01992a65\",\"reason\":\"Launch cohort allocation\"}"), params); err != nil { panic(err) }
    result, err := client.Credits().Record(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Credits.RecordAsync(new CreditsRecordOptions
    {
        CustomerId = 125,
        ProductId = 120,
        Kind = JsonConvert.DeserializeObject<SdkRecordCreditTransactionRequestApplicationJsonKind>("\"grant\"")!,
        AmountUnits = 1000,
        IdempotencyKey = "credits-grant-01992a65",
        Reason = JsonConvert.DeserializeObject<string?>("\"Launch cohort allocation\"")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.credits.record(customerId = 125L, productId = 120L, kind = app.sell.sellapp.types.SdkRecordCreditTransactionRequestApplicationJsonKind("grant"), amountUnits = 1000L, idempotencyKey = "credits-grant-01992a65", reason = "Launch cohort allocation")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.credits.record(
  customer_id: 125,
  product_id: 120,
  kind: "grant",
  amount_units: 1000,
  idempotency_key: "credits-grant-01992a65",
  reason: "Launch cohort allocation"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::credits::RecordParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = RecordParams::new(serde_json::from_str("{\"customer_id\":125,\"product_id\":120,\"kind\":\"grant\",\"amount_units\":1000,\"idempotency_key\":\"credits-grant-01992a65\",\"reason\":\"Launch cohort allocation\"}")?);
    let result = client.credits().record(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Credits.record(client, %{"customer_id" => 125, "product_id" => 120, "kind" => "grant", "amount_units" => 1000, "idempotency_key" => "credits-grant-01992a65", "reason" => "Launch cohort allocation"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp credits record --customer-id 125 --product-id 120 --kind grant --amount-units 1000 --body-idempotency-key credits-grant-01992a65 --reason 'Launch cohort allocation' --yes

```

- Method: `POST`

- Path: `/v2/credit-transactions`

- Full URL: `https://sell.app/api/v2/credit-transactions`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/credit-transactions" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "customer_id": 125,
  "product_id": 120,
  "kind": "grant",
  "amount_units": 1000,
  "idempotency_key": "credits-grant-01992a65",
  "reason": "Launch cohort allocation"
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "customer_id",
    "product_id",
    "kind",
    "amount_units",
    "idempotency_key"
  ],
  "properties": {
    "customer_id": {
      "type": "integer"
    },
    "product_id": {
      "type": "integer"
    },
    "kind": {
      "type": "string",
      "enum": [
        "grant",
        "consumption",
        "adjustment"
      ]
    },
    "amount_units": {
      "type": "integer",
      "description": "The signed amount of credit units. Must not be zero."
    },
    "idempotency_key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128
    },
    "reason": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 1000
    },
    "source_type": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 64
    },
    "source_id": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 128
    },
    "metadata": {
      "anyOf": [
        {
          "type": "object",
          "additionalProperties": true
        },
        {
          "type": "null"
        }
      ]
    }
  }
}
```

Example:

```json
{
  "customer_id": 125,
  "product_id": 120,
  "kind": "grant",
  "amount_units": 1000,
  "idempotency_key": "credits-grant-01992a65",
  "reason": "Launch cohort allocation"
}
```

## Responses

### 200

Idempotent replay.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "store_id",
        "customer_id",
        "product_id",
        "kind",
        "amount_units",
        "balance_after_units",
        "idempotency_key"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "store_id": {
          "type": "integer"
        },
        "customer_id": {
          "type": "integer"
        },
        "product_id": {
          "type": "integer"
        },
        "kind": {
          "type": "string",
          "enum": [
            "grant",
            "consumption",
            "adjustment"
          ]
        },
        "amount_units": {
          "type": "integer"
        },
        "balance_after_units": {
          "type": "integer",
          "minimum": 0
        },
        "idempotency_key": {
          "type": "string",
          "maxLength": 128
        },
        "source_type": {
          "type": [
            "string",
            "null"
          ]
        },
        "source_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "reason": {
          "type": [
            "string",
            "null"
          ]
        },
        "metadata": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": true
            },
            {
              "type": "null"
            }
          ]
        },
        "actor_user_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 601,
    "store_id": 1,
    "customer_id": 125,
    "product_id": 120,
    "kind": "grant",
    "amount_units": 1000,
    "idempotency_key": "credits-grant-01992a65",
    "reason": "Launch cohort allocation",
    "balance_after_units": 1000,
    "source_type": null,
    "source_id": null,
    "metadata": {},
    "actor_user_id": 1,
    "created_at": "2026-08-30T12:00:01.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z"
  }
}
```

### 201

Credit transaction recorded.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "store_id",
        "customer_id",
        "product_id",
        "kind",
        "amount_units",
        "balance_after_units",
        "idempotency_key"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "store_id": {
          "type": "integer"
        },
        "customer_id": {
          "type": "integer"
        },
        "product_id": {
          "type": "integer"
        },
        "kind": {
          "type": "string",
          "enum": [
            "grant",
            "consumption",
            "adjustment"
          ]
        },
        "amount_units": {
          "type": "integer"
        },
        "balance_after_units": {
          "type": "integer",
          "minimum": 0
        },
        "idempotency_key": {
          "type": "string",
          "maxLength": 128
        },
        "source_type": {
          "type": [
            "string",
            "null"
          ]
        },
        "source_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "reason": {
          "type": [
            "string",
            "null"
          ]
        },
        "metadata": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": true
            },
            {
              "type": "null"
            }
          ]
        },
        "actor_user_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 601,
    "store_id": 1,
    "customer_id": 125,
    "product_id": 120,
    "kind": "grant",
    "amount_units": 1000,
    "idempotency_key": "credits-grant-01992a65",
    "reason": "Launch cohort allocation",
    "balance_after_units": 1000,
    "source_type": null,
    "source_id": null,
    "metadata": {},
    "actor_user_id": 1,
    "created_at": "2026-08-30T12:00:01.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Replace a credits product (/docs/api/credits/replace-a-credit-product)

## PUT /v2/credit-products/{creditProduct}

Replace a credits product

Update the credits product and its single default variant atomically. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.creditsProducts.replace({
  "creditProduct": 1,
  "title": "Design credits"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.credits_products.replace(
    credit_product=1,
    title="Design credits"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->creditsProducts()->replace(
    creditProduct: 1,
    title: 'Design credits',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CreditsProductsReplaceParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Design credits\"}"), params); err != nil { panic(err) }
    result, err := client.CreditsProducts().Replace(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CreditsProducts.ReplaceAsync(
    "1",
    new CreditsProductsReplaceOptions
    {
        Title = "Design credits",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.creditsProducts.replace(creditProduct = "1", title = "Design credits")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.credits_products.replace(
  credit_product: 1,
  title: "Design credits"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::credits_products::ReplaceParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplaceParams::new(serde_json::from_str("{\"title\":\"Design credits\"}")?);
    let result = client.credits_products().replace("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CreditsProducts.replace(client, 1, %{"title" => "Design credits"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp credits products replace 1 --title 'Design credits' --yes

```

- Method: `PUT`

- Path: `/v2/credit-products/{creditProduct}`

- Full URL: `https://sell.app/api/v2/credit-products/{creditProduct}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CREDIT_PRODUCT_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/credit-products/${SELLAPP_CREDIT_PRODUCT_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Design credits"
}'
```

## Path Parameters
- `creditProduct` (`integer`, required): The creditProduct path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255
    },
    "slug": {
      "type": "string",
      "maxLength": 255,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
    },
    "description": {
      "type": "string",
      "minLength": 5,
      "maxLength": 5000
    },
    "visibility": {
      "type": "string",
      "enum": [
        "PUBLIC",
        "ON_HOLD",
        "HIDDEN",
        "PRIVATE"
      ]
    },
    "section_id": {
      "type": [
        "integer",
        "null"
      ]
    },
    "is_draft": {
      "type": "boolean",
      "default": true
    },
    "price_cents": {
      "type": "integer",
      "minimum": 0,
      "description": "Base price in integer minor currency units."
    },
    "currency": {
      "type": "string",
      "minLength": 3,
      "maxLength": 3,
      "example": "USD"
    },
    "minimum_purchase_quantity": {
      "type": "integer",
      "minimum": 1,
      "maximum": 2147483647
    },
    "maximum_purchase_quantity": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1,
      "maximum": 2147483647
    },
    "quantity_increment": {
      "type": "integer",
      "minimum": 1
    },
    "stock": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 0,
      "maximum": 2147483647
    },
    "payment_methods": {
      "type": "array",
      "uniqueItems": true,
      "items": {
        "type": "string",
        "enum": [
          "AUTHNET",
          "BTCPAY",
          "CASHAPP",
          "COINBASE",
          "PADDLE",
          "PAYDASH",
          "PAYPAL",
          "PAYSTACK",
          "SQUARE",
          "STRIPE",
          "VENMO",
          "NMI",
          "MERCADO_PAGO",
          "MOLLIE",
          "RAZORPAY",
          "CUSTOM_PAYMENT_METHOD",
          "LIFI",
          "BTC",
          "LTC",
          "ETH",
          "XMR",
          "SOL",
          "ADA",
          "BNB",
          "TRX",
          "MATIC",
          "ETH_USDT",
          "ETH_USDC",
          "ETH_UNI",
          "ETH_SHIB",
          "ETH_DAI",
          "BNB_USDT",
          "BNB_USDC",
          "TRX_USDT",
          "TRX_USDC",
          "SOL_USDT",
          "SOL_USDC"
        ]
      }
    },
    "rate_tiers": {
      "type": "array",
      "maxItems": 100,
      "items": {
        "type": "object",
        "required": [
          "min_quantity",
          "max_quantity",
          "unit_price"
        ],
        "properties": {
          "min_quantity": {
            "type": "integer",
            "minimum": 1,
            "example": 100
          },
          "max_quantity": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "example": 999
          },
          "unit_price": {
            "type": "string",
            "maxLength": 32,
            "pattern": "^\\d+(?:\\.\\d{1,4})?$",
            "description": "Positive per-credit price as a decimal string with at most four decimal places. Numeric floats and zero are not accepted.",
            "example": "0.5000"
          }
        }
      }
    },
    "expected_updated_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
```

Example (minimal):

```json
{
  "title": "Design credits"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "store_id",
        "title",
        "slug",
        "visibility",
        "type",
        "is_draft",
        "is_discoverable",
        "default_variant"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "store_id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ]
        },
        "type": {
          "type": "string",
          "const": "credits"
        },
        "is_draft": {
          "type": "boolean"
        },
        "is_discoverable": {
          "type": "boolean"
        },
        "section_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "default_variant": {
          "anyOf": [
            {
              "type": "object",
              "description": "The single sellable variant, or null when zero or multiple variants exist. When null, variant_invariant explains the issue.",
              "required": [
                "id",
                "price_cents",
                "currency",
                "minimum_purchase_quantity",
                "quantity_increment",
                "payment_methods",
                "rate_tiers"
              ],
              "properties": {
                "id": {
                  "type": "integer"
                },
                "price_cents": {
                  "type": "integer",
                  "minimum": 0
                },
                "currency": {
                  "type": "string"
                },
                "minimum_purchase_quantity": {
                  "type": "integer",
                  "minimum": 1
                },
                "maximum_purchase_quantity": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "quantity_increment": {
                  "type": "integer",
                  "minimum": 1
                },
                "stock": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                },
                "payment_methods": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "rate_tiers": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "min_quantity",
                      "max_quantity",
                      "unit_price"
                    ],
                    "properties": {
                      "min_quantity": {
                        "type": "integer",
                        "minimum": 1,
                        "example": 100
                      },
                      "max_quantity": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 1,
                        "example": 999
                      },
                      "unit_price": {
                        "type": "string",
                        "maxLength": 32,
                        "pattern": "^\\d+(?:\\.\\d{1,4})?$",
                        "description": "Positive per-credit price as a decimal string with at most four decimal places. Numeric floats and zero are not accepted.",
                        "example": "0.5000"
                      }
                    }
                  }
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "variant_invariant": {
          "type": "object",
          "description": "Present only when default_variant is null. Inspect the state before attempting a purchase.",
          "required": [
            "state",
            "variant_count"
          ],
          "properties": {
            "state": {
              "type": "string",
              "enum": [
                "missing_default_variant",
                "multiple_default_variants"
              ]
            },
            "variant_count": {
              "type": "integer",
              "minimum": 0
            }
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 121,
    "store_id": 1,
    "title": "Design credits",
    "slug": "design-credits",
    "description": "Credits for future design work.",
    "visibility": "HIDDEN",
    "type": "credits",
    "is_draft": false,
    "is_discoverable": false,
    "section_id": null,
    "default_variant": {
      "id": 4322,
      "price_cents": 50,
      "currency": "USD",
      "minimum_purchase_quantity": 1,
      "maximum_purchase_quantity": null,
      "quantity_increment": 1,
      "stock": null,
      "payment_methods": [
        "STRIPE"
      ],
      "rate_tiers": []
    },
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z",
    "deleted_at": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve a credit balance (/docs/api/credits/retrieve-a-credit-balance)

## GET /v2/credit-balances/{customer}/{creditProduct}

Retrieve a credit balance

Retrieve one customer and credits-product balance with up to 100 recent ledger entries. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.creditsBalances.get({
  "customer": 1,
  "creditProduct": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.credits_balances.get(
    customer=1,
    credit_product=1
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->creditsBalances()->get(
    customer: 1,
    creditProduct: 1,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.CreditsBalances().Get(context.Background(), 1, 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CreditsBalances.GetAsync(
    "1",
    "1"
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.creditsBalances.get(customer = "1", creditProduct = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.credits_balances.get(
  customer: 1,
  credit_product: 1
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::credits_balances::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.credits_balances().get("1", "1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CreditsBalances.get(client, 1, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp credits balances get --customer 1 1

```

- Method: `GET`

- Path: `/v2/credit-balances/{customer}/{creditProduct}`

- Full URL: `https://sell.app/api/v2/credit-balances/{customer}/{creditProduct}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CUSTOMER_ID='1'
export SELLAPP_CREDIT_PRODUCT_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/credit-balances/${SELLAPP_CUSTOMER_ID}/${SELLAPP_CREDIT_PRODUCT_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `customer` (`integer`, required): The customer path parameter.
- `creditProduct` (`integer`, required): The creditProduct path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "store_id",
        "customer_id",
        "product_id",
        "balance_units"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "store_id": {
          "type": "integer"
        },
        "customer_id": {
          "type": "integer"
        },
        "customer_email": {
          "type": [
            "string",
            "null"
          ],
          "format": "email",
          "description": "The email of the customer holding the balance, or null once the customer is deleted."
        },
        "product_id": {
          "type": "integer"
        },
        "product_title": {
          "type": [
            "string",
            "null"
          ],
          "description": "The title of the credits product, or null once the product is soft-deleted."
        },
        "balance_units": {
          "type": "integer",
          "minimum": 0
        },
        "ledger_entries": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "id",
              "store_id",
              "customer_id",
              "product_id",
              "kind",
              "amount_units",
              "balance_after_units",
              "idempotency_key"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "store_id": {
                "type": "integer"
              },
              "customer_id": {
                "type": "integer"
              },
              "product_id": {
                "type": "integer"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "grant",
                  "consumption",
                  "adjustment"
                ]
              },
              "amount_units": {
                "type": "integer"
              },
              "balance_after_units": {
                "type": "integer",
                "minimum": 0
              },
              "idempotency_key": {
                "type": "string",
                "maxLength": 128
              },
              "source_type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "source_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "reason": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "metadata": {
                "anyOf": [
                  {
                    "type": "object",
                    "additionalProperties": true
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "actor_user_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 81,
    "store_id": 1,
    "customer_id": 77,
    "customer_email": "maya@example.com",
    "product_id": 121,
    "product_title": "Design credits",
    "balance_units": 0,
    "ledger_entries": [],
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve a credits product (/docs/api/credits/retrieve-a-credit-product)

## GET /v2/credit-products/{creditProduct}

Retrieve a credits product

Retrieve a store-scoped credits product. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.creditsProducts.get({
  "creditProduct": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.credits_products.get(credit_product=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->creditsProducts()->get(creditProduct: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.CreditsProducts().Get(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CreditsProducts.GetAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.creditsProducts.get(creditProduct = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.credits_products.get(credit_product: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::credits_products::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.credits_products().get("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CreditsProducts.get(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp credits products get 1

```

- Method: `GET`

- Path: `/v2/credit-products/{creditProduct}`

- Full URL: `https://sell.app/api/v2/credit-products/{creditProduct}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CREDIT_PRODUCT_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/credit-products/${SELLAPP_CREDIT_PRODUCT_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `creditProduct` (`integer`, required): The creditProduct path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "store_id",
        "title",
        "slug",
        "visibility",
        "type",
        "is_draft",
        "is_discoverable",
        "default_variant"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "store_id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ]
        },
        "type": {
          "type": "string",
          "const": "credits"
        },
        "is_draft": {
          "type": "boolean"
        },
        "is_discoverable": {
          "type": "boolean"
        },
        "section_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "default_variant": {
          "anyOf": [
            {
              "type": "object",
              "description": "The single sellable variant, or null when zero or multiple variants exist. When null, variant_invariant explains the issue.",
              "required": [
                "id",
                "price_cents",
                "currency",
                "minimum_purchase_quantity",
                "quantity_increment",
                "payment_methods",
                "rate_tiers"
              ],
              "properties": {
                "id": {
                  "type": "integer"
                },
                "price_cents": {
                  "type": "integer",
                  "minimum": 0
                },
                "currency": {
                  "type": "string"
                },
                "minimum_purchase_quantity": {
                  "type": "integer",
                  "minimum": 1
                },
                "maximum_purchase_quantity": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "quantity_increment": {
                  "type": "integer",
                  "minimum": 1
                },
                "stock": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                },
                "payment_methods": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "rate_tiers": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "min_quantity",
                      "max_quantity",
                      "unit_price"
                    ],
                    "properties": {
                      "min_quantity": {
                        "type": "integer",
                        "minimum": 1,
                        "example": 100
                      },
                      "max_quantity": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 1,
                        "example": 999
                      },
                      "unit_price": {
                        "type": "string",
                        "maxLength": 32,
                        "pattern": "^\\d+(?:\\.\\d{1,4})?$",
                        "description": "Positive per-credit price as a decimal string with at most four decimal places. Numeric floats and zero are not accepted.",
                        "example": "0.5000"
                      }
                    }
                  }
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "variant_invariant": {
          "type": "object",
          "description": "Present only when default_variant is null. Inspect the state before attempting a purchase.",
          "required": [
            "state",
            "variant_count"
          ],
          "properties": {
            "state": {
              "type": "string",
              "enum": [
                "missing_default_variant",
                "multiple_default_variants"
              ]
            },
            "variant_count": {
              "type": "integer",
              "minimum": 0
            }
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 121,
    "store_id": 1,
    "title": "Design credits",
    "slug": "design-credits",
    "description": "Credits for future design work.",
    "visibility": "HIDDEN",
    "type": "credits",
    "is_draft": false,
    "is_discoverable": false,
    "section_id": null,
    "default_variant": {
      "id": 4322,
      "price_cents": 50,
      "currency": "USD",
      "minimum_purchase_quantity": 1,
      "maximum_purchase_quantity": null,
      "quantity_increment": 1,
      "stock": null,
      "payment_methods": [
        "STRIPE"
      ],
      "rate_tiers": []
    },
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z",
    "deleted_at": null
  }
}
```

Example (missing_default_variant):

```json
{
  "data": {
    "id": 121,
    "store_id": 1,
    "title": "Design credits",
    "slug": "design-credits",
    "description": "Credits for future design work.",
    "visibility": "HIDDEN",
    "type": "credits",
    "is_draft": false,
    "is_discoverable": false,
    "section_id": null,
    "default_variant": null,
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z",
    "deleted_at": null,
    "variant_invariant": {
      "state": "missing_default_variant",
      "variant_count": 0
    }
  }
}
```

Example (multiple_default_variants):

```json
{
  "data": {
    "id": 121,
    "store_id": 1,
    "title": "Design credits",
    "slug": "design-credits",
    "description": "Credits for future design work.",
    "visibility": "HIDDEN",
    "type": "credits",
    "is_draft": false,
    "is_discoverable": false,
    "section_id": null,
    "default_variant": null,
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z",
    "deleted_at": null,
    "variant_invariant": {
      "state": "multiple_default_variants",
      "variant_count": 2
    }
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Search credits products (/docs/api/credits/search-credit-products)

## POST /v2/credit-products/search

Search credits products

Search credits products by title, slug, or description. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.creditsProducts.search({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.credits_products.search()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->creditsProducts()->search();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CreditsProductsSearchParams{}
    if err := json.Unmarshal([]byte("{}"), params); err != nil { panic(err) }
    page := client.CreditsProducts().Search(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CreditsProducts.SearchAsync(new CreditsProductsSearchOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.creditsProducts.search()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.credits_products.search
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::credits_products::SearchParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = SearchParams::new(serde_json::from_str("{}")?);
    let result = client.credits_products().search(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CreditsProducts.search(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp credits products search

```

- Method: `POST`

- Path: `/v2/credit-products/search`

- Full URL: `https://sell.app/api/v2/credit-products/search`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/credit-products/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching items in one data array without pagination links or metadata.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

- Description: Omit the body to list matching products. Filter fields: id, visibility, is_draft. Sort fields: id, title, created_at, updated_at. Search matches title, slug, or description. No includes are supported.

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "id",
              "visibility",
              "is_draft"
            ]
          },
          "operator": {
            "type": "string",
            "default": "="
          },
          "value": {},
          "type": {
            "type": "string",
            "enum": [
              "and",
              "or"
            ],
            "default": "and"
          },
          "nested": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "anyOf": [
          {
            "required": [
              "field"
            ]
          },
          {
            "required": [
              "nested"
            ]
          }
        ]
      }
    },
    "sort": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "id",
              "title",
              "created_at",
              "updated_at"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "default": "asc"
          }
        },
        "required": [
          "field"
        ]
      }
    },
    "search": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "null"
          ]
        },
        "case_sensitive": {
          "type": "boolean"
        }
      }
    },
    "includes": {
      "type": "array",
      "maxItems": 0,
      "items": {
        "type": "object"
      }
    }
  }
}
```

Example (minimal):

```json
{}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "id",
              "store_id",
              "title",
              "slug",
              "visibility",
              "type",
              "is_draft",
              "is_discoverable",
              "default_variant"
            ],
            "properties": {
              "id": {
                "type": "integer",
                "example": 1
              },
              "store_id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ]
              },
              "type": {
                "type": "string",
                "const": "credits"
              },
              "is_draft": {
                "type": "boolean"
              },
              "is_discoverable": {
                "type": "boolean"
              },
              "section_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "default_variant": {
                "anyOf": [
                  {
                    "type": "object",
                    "description": "The single sellable variant, or null when zero or multiple variants exist. When null, variant_invariant explains the issue.",
                    "required": [
                      "id",
                      "price_cents",
                      "currency",
                      "minimum_purchase_quantity",
                      "quantity_increment",
                      "payment_methods",
                      "rate_tiers"
                    ],
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "price_cents": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "currency": {
                        "type": "string"
                      },
                      "minimum_purchase_quantity": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "maximum_purchase_quantity": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "quantity_increment": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "stock": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 0
                      },
                      "payment_methods": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "rate_tiers": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "required": [
                            "min_quantity",
                            "max_quantity",
                            "unit_price"
                          ],
                          "properties": {
                            "min_quantity": {
                              "type": "integer",
                              "minimum": 1,
                              "example": 100
                            },
                            "max_quantity": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 1,
                              "example": 999
                            },
                            "unit_price": {
                              "type": "string",
                              "maxLength": 32,
                              "pattern": "^\\d+(?:\\.\\d{1,4})?$",
                              "description": "Positive per-credit price as a decimal string with at most four decimal places. Numeric floats and zero are not accepted.",
                              "example": "0.5000"
                            }
                          }
                        }
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "variant_invariant": {
                "type": "object",
                "description": "Present only when default_variant is null. Inspect the state before attempting a purchase.",
                "required": [
                  "state",
                  "variant_count"
                ],
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "missing_default_variant",
                      "multiple_default_variants"
                    ]
                  },
                  "variant_count": {
                    "type": "integer",
                    "minimum": 0
                  }
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "id",
              "store_id",
              "title",
              "slug",
              "visibility",
              "type",
              "is_draft",
              "is_discoverable",
              "default_variant"
            ],
            "properties": {
              "id": {
                "type": "integer",
                "example": 1
              },
              "store_id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "visibility": {
                "type": "string",
                "enum": [
                  "PUBLIC",
                  "ON_HOLD",
                  "HIDDEN",
                  "PRIVATE"
                ]
              },
              "type": {
                "type": "string",
                "const": "credits"
              },
              "is_draft": {
                "type": "boolean"
              },
              "is_discoverable": {
                "type": "boolean"
              },
              "section_id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "default_variant": {
                "anyOf": [
                  {
                    "type": "object",
                    "description": "The single sellable variant, or null when zero or multiple variants exist. When null, variant_invariant explains the issue.",
                    "required": [
                      "id",
                      "price_cents",
                      "currency",
                      "minimum_purchase_quantity",
                      "quantity_increment",
                      "payment_methods",
                      "rate_tiers"
                    ],
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "price_cents": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "currency": {
                        "type": "string"
                      },
                      "minimum_purchase_quantity": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "maximum_purchase_quantity": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "quantity_increment": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "stock": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 0
                      },
                      "payment_methods": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "rate_tiers": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "required": [
                            "min_quantity",
                            "max_quantity",
                            "unit_price"
                          ],
                          "properties": {
                            "min_quantity": {
                              "type": "integer",
                              "minimum": 1,
                              "example": 100
                            },
                            "max_quantity": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "minimum": 1,
                              "example": 999
                            },
                            "unit_price": {
                              "type": "string",
                              "maxLength": 32,
                              "pattern": "^\\d+(?:\\.\\d{1,4})?$",
                              "description": "Positive per-credit price as a decimal string with at most four decimal places. Numeric floats and zero are not accepted.",
                              "example": "0.5000"
                            }
                          }
                        }
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "variant_invariant": {
                "type": "object",
                "description": "Present only when default_variant is null. Inspect the state before attempting a purchase.",
                "required": [
                  "state",
                  "variant_count"
                ],
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "missing_default_variant",
                      "multiple_default_variants"
                    ]
                  },
                  "variant_count": {
                    "type": "integer",
                    "minimum": 0
                  }
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example (minimal):

```json
{
  "data": [],
  "links": {
    "first": "https://sell.app/api/v2/credit-products/search?page=1",
    "last": "https://sell.app/api/v2/credit-products/search?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": null,
    "last_page": 1,
    "links": [
      {
        "url": "string",
        "label": "string",
        "active": true
      }
    ],
    "path": "https://sell.app/api/v2/credit-products/search",
    "per_page": 15,
    "to": null,
    "total": 0
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Update a credits product (/docs/api/credits/update-a-credit-product)

## PATCH /v2/credit-products/{creditProduct}

Update a credits product

Update the credits product and its single default variant atomically. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.creditsProducts.update({
  "creditProduct": 1,
  "title": "Design credits"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.credits_products.update(
    credit_product=1,
    title="Design credits"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->creditsProducts()->update(
    creditProduct: 1,
    title: 'Design credits',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CreditsProductsUpdateParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Design credits\"}"), params); err != nil { panic(err) }
    result, err := client.CreditsProducts().Update(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.CreditsProducts.UpdateAsync(
    "1",
    new CreditsProductsUpdateOptions
    {
        Title = "Design credits",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.creditsProducts.update(creditProduct = "1", title = app.sell.sellapp.common.http.PatchField.Present("Design credits"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.credits_products.update(
  credit_product: 1,
  title: "Design credits"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::credits_products::UpdateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateParams::new(serde_json::from_str("{\"title\":\"Design credits\"}")?);
    let result = client.credits_products().update("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.CreditsProducts.update(client, 1, %{"title" => "Design credits"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp credits products update 1 --title 'Design credits' --yes

```

- Method: `PATCH`

- Path: `/v2/credit-products/{creditProduct}`

- Full URL: `https://sell.app/api/v2/credit-products/{creditProduct}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CREDIT_PRODUCT_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/credit-products/${SELLAPP_CREDIT_PRODUCT_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Design credits"
}'
```

## Path Parameters
- `creditProduct` (`integer`, required): The creditProduct path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 255
    },
    "slug": {
      "type": "string",
      "maxLength": 255,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
    },
    "description": {
      "type": "string",
      "minLength": 5,
      "maxLength": 5000
    },
    "visibility": {
      "type": "string",
      "enum": [
        "PUBLIC",
        "ON_HOLD",
        "HIDDEN",
        "PRIVATE"
      ]
    },
    "section_id": {
      "type": [
        "integer",
        "null"
      ]
    },
    "is_draft": {
      "type": "boolean",
      "default": true
    },
    "price_cents": {
      "type": "integer",
      "minimum": 0,
      "description": "Base price in integer minor currency units."
    },
    "currency": {
      "type": "string",
      "minLength": 3,
      "maxLength": 3,
      "example": "USD"
    },
    "minimum_purchase_quantity": {
      "type": "integer",
      "minimum": 1,
      "maximum": 2147483647
    },
    "maximum_purchase_quantity": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1,
      "maximum": 2147483647
    },
    "quantity_increment": {
      "type": "integer",
      "minimum": 1
    },
    "stock": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 0,
      "maximum": 2147483647
    },
    "payment_methods": {
      "type": "array",
      "uniqueItems": true,
      "items": {
        "type": "string",
        "enum": [
          "AUTHNET",
          "BTCPAY",
          "CASHAPP",
          "COINBASE",
          "PADDLE",
          "PAYDASH",
          "PAYPAL",
          "PAYSTACK",
          "SQUARE",
          "STRIPE",
          "VENMO",
          "NMI",
          "MERCADO_PAGO",
          "MOLLIE",
          "RAZORPAY",
          "CUSTOM_PAYMENT_METHOD",
          "LIFI",
          "BTC",
          "LTC",
          "ETH",
          "XMR",
          "SOL",
          "ADA",
          "BNB",
          "TRX",
          "MATIC",
          "ETH_USDT",
          "ETH_USDC",
          "ETH_UNI",
          "ETH_SHIB",
          "ETH_DAI",
          "BNB_USDT",
          "BNB_USDC",
          "TRX_USDT",
          "TRX_USDC",
          "SOL_USDT",
          "SOL_USDC"
        ]
      }
    },
    "rate_tiers": {
      "type": "array",
      "maxItems": 100,
      "items": {
        "type": "object",
        "required": [
          "min_quantity",
          "max_quantity",
          "unit_price"
        ],
        "properties": {
          "min_quantity": {
            "type": "integer",
            "minimum": 1,
            "example": 100
          },
          "max_quantity": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "example": 999
          },
          "unit_price": {
            "type": "string",
            "maxLength": 32,
            "pattern": "^\\d+(?:\\.\\d{1,4})?$",
            "description": "Positive per-credit price as a decimal string with at most four decimal places. Numeric floats and zero are not accepted.",
            "example": "0.5000"
          }
        }
      }
    },
    "expected_updated_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
```

Example (minimal):

```json
{
  "title": "Design credits"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "store_id",
        "title",
        "slug",
        "visibility",
        "type",
        "is_draft",
        "is_discoverable",
        "default_variant"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "store_id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "visibility": {
          "type": "string",
          "enum": [
            "PUBLIC",
            "ON_HOLD",
            "HIDDEN",
            "PRIVATE"
          ]
        },
        "type": {
          "type": "string",
          "const": "credits"
        },
        "is_draft": {
          "type": "boolean"
        },
        "is_discoverable": {
          "type": "boolean"
        },
        "section_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "default_variant": {
          "anyOf": [
            {
              "type": "object",
              "description": "The single sellable variant, or null when zero or multiple variants exist. When null, variant_invariant explains the issue.",
              "required": [
                "id",
                "price_cents",
                "currency",
                "minimum_purchase_quantity",
                "quantity_increment",
                "payment_methods",
                "rate_tiers"
              ],
              "properties": {
                "id": {
                  "type": "integer"
                },
                "price_cents": {
                  "type": "integer",
                  "minimum": 0
                },
                "currency": {
                  "type": "string"
                },
                "minimum_purchase_quantity": {
                  "type": "integer",
                  "minimum": 1
                },
                "maximum_purchase_quantity": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "quantity_increment": {
                  "type": "integer",
                  "minimum": 1
                },
                "stock": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0
                },
                "payment_methods": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "rate_tiers": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "min_quantity",
                      "max_quantity",
                      "unit_price"
                    ],
                    "properties": {
                      "min_quantity": {
                        "type": "integer",
                        "minimum": 1,
                        "example": 100
                      },
                      "max_quantity": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "minimum": 1,
                        "example": 999
                      },
                      "unit_price": {
                        "type": "string",
                        "maxLength": 32,
                        "pattern": "^\\d+(?:\\.\\d{1,4})?$",
                        "description": "Positive per-credit price as a decimal string with at most four decimal places. Numeric floats and zero are not accepted.",
                        "example": "0.5000"
                      }
                    }
                  }
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "variant_invariant": {
          "type": "object",
          "description": "Present only when default_variant is null. Inspect the state before attempting a purchase.",
          "required": [
            "state",
            "variant_count"
          ],
          "properties": {
            "state": {
              "type": "string",
              "enum": [
                "missing_default_variant",
                "multiple_default_variants"
              ]
            },
            "variant_count": {
              "type": "integer",
              "minimum": 0
            }
          }
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example (minimal):

```json
{
  "data": {
    "id": 121,
    "store_id": 1,
    "title": "Design credits",
    "slug": "design-credits",
    "description": "Credits for future design work.",
    "visibility": "HIDDEN",
    "type": "credits",
    "is_draft": false,
    "is_discoverable": false,
    "section_id": null,
    "default_variant": {
      "id": 4322,
      "price_cents": 50,
      "currency": "USD",
      "minimum_purchase_quantity": 1,
      "maximum_purchase_quantity": null,
      "quantity_increment": 1,
      "stock": null,
      "payment_methods": [
        "STRIPE"
      ],
      "rate_tiers": []
    },
    "created_at": "2026-09-01T12:00:00Z",
    "updated_at": "2026-09-01T12:00:00Z",
    "deleted_at": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Customer identity and access (/docs/api/customers/identity-and-entitlements)

Use `external_id` to join a SellApp customer to your own system. It is unique and immutable inside a store. Email addresses are normalized before uniqueness checks; locale uses BCP 47; metadata accepts only a small map of scalar values.

Entitlements summarize access from purchases, licenses, subscriptions, bookings,
and community grants. They do not establish current membership at an external
provider. The summary omits license keys, serials, files, fulfillment payloads,
and seller-only metadata.

These operations require the API key's `invoice` ability, or `orders:read` for
OAuth reads and `orders:write` for OAuth mutations. Send `X-STORE`; current store
permissions also apply.

## POST /v2/customers

Create a customer

Create a customer with normalized unique email and immutable-per-store external_id. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.customers.createCustomer({
  "externalId": "crm_maya_314",
  "email": "maya.chen@example.com",
  "name": "Maya Chen",
  "locale": "en-GB",
  "metadata": {"plan": "standard", "seats": 3}
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.customers.create_customer(
    external_id="crm_maya_314",
    email="maya.chen@example.com",
    name="Maya Chen",
    locale="en-GB",
    metadata={"plan": "standard", "seats": 3}
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->customers()->createCustomer(
    externalId: 'crm_maya_314',
    email: 'maya.chen@example.com',
    name: 'Maya Chen',
    locale: 'en-GB',
    metadata: ['plan' => 'standard', 'seats' => 3],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CustomersCreateParams{}
    if err := json.Unmarshal([]byte("{\"external_id\":\"crm_maya_314\",\"email\":\"maya.chen@example.com\",\"name\":\"Maya Chen\",\"locale\":\"en-GB\",\"metadata\":{\"plan\":\"standard\",\"seats\":3}}"), params); err != nil { panic(err) }
    result, err := client.Customers().Create(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Customers.CreateAsync(new CustomersCreateOptions
    {
        ExternalId = "crm_maya_314",
        Email = "maya.chen@example.com",
        Name = JsonConvert.DeserializeObject<string?>("\"Maya Chen\"")!,
        Locale = JsonConvert.DeserializeObject<string?>("\"en-GB\"")!,
        Metadata = JsonConvert.DeserializeObject<CreateCustomerRequestApplicationJsonPropertyMetadata>("{\"plan\":\"standard\",\"seats\":3}")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.customers.create(externalId = "crm_maya_314", email = "maya.chen@example.com", name = "Maya Chen", locale = "en-GB", metadata = ObjectMapperFactory.read("{\"plan\":\"standard\",\"seats\":3}", app.sell.sellapp.models.CreateCustomerRequestApplicationJsonPropertyMetadata::class.java))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.customers.create_customer(
  external_id: "crm_maya_314",
  email: "maya.chen@example.com",
  name: "Maya Chen",
  locale: "en-GB",
  metadata: { plan: "standard", seats: 3 }
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customers::CreateCustomerParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateCustomerParams::new(serde_json::from_str("{\"id\":314,\"email\":\"maya.chen@example.com\",\"external_id\":\"crm_maya_314\",\"name\":\"Maya Chen\",\"locale\":\"en-GB\",\"metadata\":{\"plan\":\"standard\",\"seats\":3}}")?);
    let result = client.customers().create_customer(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Customers.create_customer(client, %{"external_id" => "crm_maya_314", "email" => "maya.chen@example.com", "name" => "Maya Chen", "locale" => "en-GB", "metadata" => %{"plan" => "standard", "seats" => 3}})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customers create-customer --body '{"id":314,"email":"maya.chen@example.com","external_id":"crm_maya_314","name":"Maya Chen","locale":"en-GB","metadata":{"plan":"standard","seats":3}}' --yes

```

- Method: `POST`

- Path: `/v2/customers`

- Full URL: `https://sell.app/api/v2/customers`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/customers" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "id": 314,
  "email": "maya.chen@example.com",
  "external_id": "crm_maya_314",
  "name": "Maya Chen",
  "locale": "en-GB",
  "metadata": {
    "plan": "standard",
    "seats": 3
  }
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, optional): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "external_id": {
      "type": "string",
      "maxLength": 255
    },
    "email": {
      "type": "string",
      "format": "email",
      "maxLength": 255
    },
    "name": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 255
    },
    "locale": {
      "type": [
        "string",
        "null"
      ],
      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
      "maxLength": 35
    },
    "metadata": {
      "type": "object",
      "maxProperties": 50,
      "propertyNames": {
        "maxLength": 40
      },
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string",
            "maxLength": 500
          },
          {
            "type": "number"
          },
          {
            "type": "boolean"
          }
        ]
      }
    }
  },
  "required": [
    "email"
  ]
}
```

Example:

```json
{
  "id": 314,
  "email": "maya.chen@example.com",
  "external_id": "crm_maya_314",
  "name": "Maya Chen",
  "locale": "en-GB",
  "metadata": {
    "plan": "standard",
    "seats": 3
  }
}
```

## Responses

### 201

Created.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A store-scoped customer profile. Checkout IP, billing, location, and community identity data are intentionally excluded.",
      "required": [
        "id",
        "email",
        "external_id",
        "name",
        "locale",
        "metadata",
        "insights",
        "created_at",
        "updated_at"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "external_id": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "name": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "locale": {
          "type": [
            "string",
            "null"
          ],
          "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
        },
        "metadata": {
          "type": "object",
          "maxProperties": 50,
          "additionalProperties": {
            "oneOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "insights": {
          "type": "object",
          "required": [
            "orders_count",
            "line_items_count",
            "completed_line_items_count",
            "pending_line_items_count",
            "voided_line_items_count",
            "subscriptions_count",
            "revenue_usd_cents",
            "first_purchase_at",
            "last_purchase_at",
            "favorite_payment_method"
          ],
          "properties": {
            "orders_count": {
              "type": "integer",
              "minimum": 0,
              "example": 3
            },
            "line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 4
            },
            "completed_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 3
            },
            "pending_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 1
            },
            "voided_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 0
            },
            "subscriptions_count": {
              "type": "integer",
              "minimum": 0,
              "example": 1
            },
            "revenue_usd_cents": {
              "type": "integer",
              "description": "Completed line-item revenue in integer USD minor units.",
              "example": 10900
            },
            "first_purchase_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "last_purchase_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "favorite_payment_method": {
              "type": [
                "string",
                "null"
              ],
              "description": "The most frequently used line-item payment method.",
              "example": "STRIPE"
            }
          }
        },
        "wallet": {
          "description": "Wallet status and balance. Omitted unless the token and staff role have wallet or store management permission.",
          "oneOf": [
            {
              "type": "null"
            },
            {
              "type": "object",
              "required": [
                "status",
                "balance_cents"
              ],
              "properties": {
                "status": {
                  "type": "string",
                  "enum": [
                    "active",
                    "frozen"
                  ]
                },
                "balance_cents": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Current wallet balance in integer USD minor units.",
                  "example": 2500
                }
              }
            }
          ]
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 314,
    "email": "maya.chen@example.com",
    "external_id": "crm_maya_314",
    "name": "Maya Chen",
    "locale": "en-GB",
    "metadata": {
      "plan": "standard",
      "seats": 3
    },
    "insights": {
      "orders_count": 0,
      "line_items_count": 0,
      "completed_line_items_count": 0,
      "pending_line_items_count": 0,
      "voided_line_items_count": 0,
      "subscriptions_count": 0,
      "revenue_usd_cents": 0,
      "first_purchase_at": null,
      "last_purchase_at": null,
      "favorite_payment_method": null
    },
    "created_at": "2026-08-24T10:00:00.000000Z",
    "updated_at": "2026-08-24T10:00:00.000000Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v2/customers/{customer}

Update a customer

Update name, BCP 47 locale, normalized email, or constrained scalar metadata. Assign external_id when it is unset; changing an existing external_id returns 409. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.customers.updateCustomer({
  "customer": 314,
  "locale": "en-US"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.customers.update_customer(
    customer=314,
    locale="en-US"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->customers()->updateCustomer(
    customer: 314,
    locale: 'en-US',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CustomersUpdateParams{}
    if err := json.Unmarshal([]byte("{\"locale\":\"en-US\"}"), params); err != nil { panic(err) }
    result, err := client.Customers().Update(context.Background(), 314, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Customers.UpdateAsync(
    "314",
    new CustomersUpdateOptions
    {
        Locale = JsonConvert.DeserializeObject<string?>("\"en-US\"")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.customers.update(customer = "314", locale = app.sell.sellapp.common.http.PatchField.Present("en-US"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.customers.update_customer(
  customer: 314,
  locale: "en-US"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customers::UpdateCustomerParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateCustomerParams::new(serde_json::from_str("{\"locale\":\"en-US\"}")?);
    let result = client.customers().update_customer("314", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Customers.update_customer(client, 314, %{"locale" => "en-US"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customers update-customer 314 --locale en-US --yes

```

- Method: `PATCH`

- Path: `/v2/customers/{customer}`

- Full URL: `https://sell.app/api/v2/customers/{customer}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CUSTOMER_ID='314'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/customers/${SELLAPP_CUSTOMER_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "locale": "en-US"
}'
```

## Path Parameters
- `customer` (`integer`, required): The customer identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, optional): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "format": "email",
      "maxLength": 255
    },
    "name": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 255
    },
    "locale": {
      "type": [
        "string",
        "null"
      ],
      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
      "maxLength": 35
    },
    "metadata": {
      "type": "object",
      "maxProperties": 50,
      "propertyNames": {
        "maxLength": 40
      },
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string",
            "maxLength": 500
          },
          {
            "type": "number"
          },
          {
            "type": "boolean"
          }
        ]
      }
    },
    "external_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 255,
      "description": "May be assigned when unset; an existing value is immutable."
    }
  }
}
```

Example:

```json
{
  "locale": "en-US"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A store-scoped customer profile. Checkout IP, billing, location, and community identity data are intentionally excluded.",
      "required": [
        "id",
        "email",
        "external_id",
        "name",
        "locale",
        "metadata",
        "insights",
        "created_at",
        "updated_at"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "external_id": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "name": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "locale": {
          "type": [
            "string",
            "null"
          ],
          "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
        },
        "metadata": {
          "type": "object",
          "maxProperties": 50,
          "additionalProperties": {
            "oneOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "insights": {
          "type": "object",
          "required": [
            "orders_count",
            "line_items_count",
            "completed_line_items_count",
            "pending_line_items_count",
            "voided_line_items_count",
            "subscriptions_count",
            "revenue_usd_cents",
            "first_purchase_at",
            "last_purchase_at",
            "favorite_payment_method"
          ],
          "properties": {
            "orders_count": {
              "type": "integer",
              "minimum": 0,
              "example": 3
            },
            "line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 4
            },
            "completed_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 3
            },
            "pending_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 1
            },
            "voided_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 0
            },
            "subscriptions_count": {
              "type": "integer",
              "minimum": 0,
              "example": 1
            },
            "revenue_usd_cents": {
              "type": "integer",
              "description": "Completed line-item revenue in integer USD minor units.",
              "example": 10900
            },
            "first_purchase_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "last_purchase_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "favorite_payment_method": {
              "type": [
                "string",
                "null"
              ],
              "description": "The most frequently used line-item payment method.",
              "example": "STRIPE"
            }
          }
        },
        "wallet": {
          "description": "Wallet status and balance. Omitted unless the token and staff role have wallet or store management permission.",
          "oneOf": [
            {
              "type": "null"
            },
            {
              "type": "object",
              "required": [
                "status",
                "balance_cents"
              ],
              "properties": {
                "status": {
                  "type": "string",
                  "enum": [
                    "active",
                    "frozen"
                  ]
                },
                "balance_cents": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Current wallet balance in integer USD minor units.",
                  "example": 2500
                }
              }
            }
          ]
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 314,
    "email": "maya.chen@example.com",
    "external_id": "crm_maya_314",
    "name": "Maya Chen",
    "locale": "en-US",
    "metadata": {
      "plan": "standard",
      "seats": 3
    },
    "insights": {
      "orders_count": 0,
      "line_items_count": 0,
      "completed_line_items_count": 0,
      "pending_line_items_count": 0,
      "voided_line_items_count": 0,
      "subscriptions_count": 0,
      "revenue_usd_cents": 0,
      "first_purchase_at": null,
      "last_purchase_at": null,
      "favorite_payment_method": null
    },
    "created_at": "2026-08-24T10:00:00.000000Z",
    "updated_at": "2026-08-24T10:00:00.000000Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/customers/external/{externalId}

Retrieve a customer by external ID

Resolve by immutable store-local external ID. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.customers.getCustomerByExternalId({
  "externalId": "314"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.customers.get_customer_by_external_id(external_id="314")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->customers()->getCustomerByExternalId(externalId: '314');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Customers().GetByExternalID(context.Background(), "314")
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Customers.GetByExternalIdAsync("314");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.customers.getByExternalId(externalId = "314")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.customers.get_customer_by_external_id(external_id: "314")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customers::GetCustomerByExternalIdParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetCustomerByExternalIdParams::default();
    let result = client.customers().get_customer_by_external_id("314", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Customers.get_customer_by_external_id(client, "314")
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customers get-customer-by-external-id 314

```

- Method: `GET`

- Path: `/v2/customers/external/{externalId}`

- Full URL: `https://sell.app/api/v2/customers/external/{externalId}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_EXTERNAL_ID='314'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/customers/external/${SELLAPP_EXTERNAL_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `externalId` (`string`, required): The externalId identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A store-scoped customer profile. Checkout IP, billing, location, and community identity data are intentionally excluded.",
      "required": [
        "id",
        "email",
        "external_id",
        "name",
        "locale",
        "metadata",
        "insights",
        "created_at",
        "updated_at"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "external_id": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "name": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "locale": {
          "type": [
            "string",
            "null"
          ],
          "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
        },
        "metadata": {
          "type": "object",
          "maxProperties": 50,
          "additionalProperties": {
            "oneOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "insights": {
          "type": "object",
          "required": [
            "orders_count",
            "line_items_count",
            "completed_line_items_count",
            "pending_line_items_count",
            "voided_line_items_count",
            "subscriptions_count",
            "revenue_usd_cents",
            "first_purchase_at",
            "last_purchase_at",
            "favorite_payment_method"
          ],
          "properties": {
            "orders_count": {
              "type": "integer",
              "minimum": 0,
              "example": 3
            },
            "line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 4
            },
            "completed_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 3
            },
            "pending_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 1
            },
            "voided_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 0
            },
            "subscriptions_count": {
              "type": "integer",
              "minimum": 0,
              "example": 1
            },
            "revenue_usd_cents": {
              "type": "integer",
              "description": "Completed line-item revenue in integer USD minor units.",
              "example": 10900
            },
            "first_purchase_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "last_purchase_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "favorite_payment_method": {
              "type": [
                "string",
                "null"
              ],
              "description": "The most frequently used line-item payment method.",
              "example": "STRIPE"
            }
          }
        },
        "wallet": {
          "description": "Wallet status and balance. Omitted unless the token and staff role have wallet or store management permission.",
          "oneOf": [
            {
              "type": "null"
            },
            {
              "type": "object",
              "required": [
                "status",
                "balance_cents"
              ],
              "properties": {
                "status": {
                  "type": "string",
                  "enum": [
                    "active",
                    "frozen"
                  ]
                },
                "balance_cents": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Current wallet balance in integer USD minor units.",
                  "example": 2500
                }
              }
            }
          ]
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 314,
    "email": "maya.chen@example.com",
    "external_id": "crm_maya_314",
    "name": "Maya Chen",
    "locale": "en-GB",
    "metadata": {
      "plan": "standard",
      "seats": 3
    },
    "insights": {
      "orders_count": 0,
      "line_items_count": 0,
      "completed_line_items_count": 0,
      "pending_line_items_count": 0,
      "voided_line_items_count": 0,
      "subscriptions_count": 0,
      "revenue_usd_cents": 0,
      "first_purchase_at": null,
      "last_purchase_at": null,
      "favorite_payment_method": null
    },
    "created_at": "2026-08-24T10:00:00.000000Z",
    "updated_at": "2026-08-24T10:00:00.000000Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## PATCH /v2/customers/external/{externalId}

Update a customer by external ID

Update the customer resolved by immutable external ID. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.customers.updateCustomerByExternalId({
  "externalId": "314",
  "locale": "en-US"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.customers.update_customer_by_external_id(
    external_id="314",
    locale="en-US"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->customers()->updateCustomerByExternalId(
    externalId: '314',
    locale: 'en-US',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CustomersUpdateByExternalIDParams{}
    if err := json.Unmarshal([]byte("{\"locale\":\"en-US\"}"), params); err != nil { panic(err) }
    result, err := client.Customers().UpdateByExternalID(context.Background(), "314", params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Customers.UpdateByExternalIdAsync(
    "314",
    new CustomersUpdateByExternalIdOptions
    {
        Locale = JsonConvert.DeserializeObject<string?>("\"en-US\"")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.customers.updateByExternalId(externalId = "314", locale = app.sell.sellapp.common.http.PatchField.Present("en-US"))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.customers.update_customer_by_external_id(
  external_id: "314",
  locale: "en-US"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customers::UpdateCustomerByExternalIdParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = UpdateCustomerByExternalIdParams::new(serde_json::from_str("{\"locale\":\"en-US\"}")?);
    let result = client.customers().update_customer_by_external_id("314", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Customers.update_customer_by_external_id(client, "314", %{"locale" => "en-US"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customers update-customer-by-external-id 314 --locale en-US --yes

```

- Method: `PATCH`

- Path: `/v2/customers/external/{externalId}`

- Full URL: `https://sell.app/api/v2/customers/external/{externalId}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_EXTERNAL_ID='314'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/customers/external/${SELLAPP_EXTERNAL_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "locale": "en-US"
}'
```

## Path Parameters
- `externalId` (`string`, required): The externalId identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, optional): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "format": "email",
      "maxLength": 255
    },
    "name": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 255
    },
    "locale": {
      "type": [
        "string",
        "null"
      ],
      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
      "maxLength": 35
    },
    "metadata": {
      "type": "object",
      "maxProperties": 50,
      "propertyNames": {
        "maxLength": 40
      },
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string",
            "maxLength": 500
          },
          {
            "type": "number"
          },
          {
            "type": "boolean"
          }
        ]
      }
    }
  }
}
```

Example:

```json
{
  "locale": "en-US"
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "description": "A store-scoped customer profile. Checkout IP, billing, location, and community identity data are intentionally excluded.",
      "required": [
        "id",
        "email",
        "external_id",
        "name",
        "locale",
        "metadata",
        "insights",
        "created_at",
        "updated_at"
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "external_id": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "name": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "locale": {
          "type": [
            "string",
            "null"
          ],
          "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
        },
        "metadata": {
          "type": "object",
          "maxProperties": 50,
          "additionalProperties": {
            "oneOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "insights": {
          "type": "object",
          "required": [
            "orders_count",
            "line_items_count",
            "completed_line_items_count",
            "pending_line_items_count",
            "voided_line_items_count",
            "subscriptions_count",
            "revenue_usd_cents",
            "first_purchase_at",
            "last_purchase_at",
            "favorite_payment_method"
          ],
          "properties": {
            "orders_count": {
              "type": "integer",
              "minimum": 0,
              "example": 3
            },
            "line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 4
            },
            "completed_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 3
            },
            "pending_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 1
            },
            "voided_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 0
            },
            "subscriptions_count": {
              "type": "integer",
              "minimum": 0,
              "example": 1
            },
            "revenue_usd_cents": {
              "type": "integer",
              "description": "Completed line-item revenue in integer USD minor units.",
              "example": 10900
            },
            "first_purchase_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "last_purchase_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "favorite_payment_method": {
              "type": [
                "string",
                "null"
              ],
              "description": "The most frequently used line-item payment method.",
              "example": "STRIPE"
            }
          }
        },
        "wallet": {
          "description": "Wallet status and balance. Omitted unless the token and staff role have wallet or store management permission.",
          "oneOf": [
            {
              "type": "null"
            },
            {
              "type": "object",
              "required": [
                "status",
                "balance_cents"
              ],
              "properties": {
                "status": {
                  "type": "string",
                  "enum": [
                    "active",
                    "frozen"
                  ]
                },
                "balance_cents": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Current wallet balance in integer USD minor units.",
                  "example": 2500
                }
              }
            }
          ]
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": 314,
    "email": "maya.chen@example.com",
    "external_id": "crm_maya_314",
    "name": "Maya Chen",
    "locale": "en-US",
    "metadata": {
      "plan": "standard",
      "seats": 3
    },
    "insights": {
      "orders_count": 0,
      "line_items_count": 0,
      "completed_line_items_count": 0,
      "pending_line_items_count": 0,
      "voided_line_items_count": 0,
      "subscriptions_count": 0,
      "revenue_usd_cents": 0,
      "first_purchase_at": null,
      "last_purchase_at": null,
      "favorite_payment_method": null
    },
    "created_at": "2026-08-24T10:00:00.000000Z",
    "updated_at": "2026-08-24T10:00:00.000000Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/customers/{customer}/entitlements

List customer entitlements

Unified access without raw keys, serials, files, dynamic payloads, or seller-only metadata. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.entitlements.listCustomerEntitlements({
  "customer": 42
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.entitlements.list_customer_entitlements(customer=42)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->entitlements()->listCustomerEntitlements(customer: 42);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Entitlements().ListCustomerEntitlements(context.Background(), 42)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Entitlements.ListCustomerEntitlementsAsync("42");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.entitlements.listCustomerEntitlements(customer = "42")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.entitlements.list_customer_entitlements(customer: 42)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::entitlements::ListCustomerEntitlementsParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListCustomerEntitlementsParams::default();
    let result = client.entitlements().list_customer_entitlements("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Entitlements.list_customer_entitlements(client, 42)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp entitlements list-customer-entitlements 42

```

- Method: `GET`

- Path: `/v2/customers/{customer}/entitlements`

- Full URL: `https://sell.app/api/v2/customers/{customer}/entitlements`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CUSTOMER_ID='42'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/customers/${SELLAPP_CUSTOMER_ID}/entitlements" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `customer` (`integer`, required): The customer identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "state",
          "customer_id",
          "subject"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z_]+:[A-Za-z0-9-]+$"
          },
          "kind": {
            "type": "string",
            "enum": [
              "delivered_product",
              "license",
              "community_grant",
              "booking",
              "subscription_access"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "suspended",
              "expired",
              "revoked",
              "failed",
              "action_required"
            ]
          },
          "customer_id": {
            "type": "integer"
          },
          "subject": {
            "type": "object",
            "required": [
              "type",
              "id",
              "name"
            ],
            "properties": {
              "type": {
                "type": "string"
              },
              "id": {
                "type": [
                  "integer",
                  "string"
                ]
              },
              "name": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "id": "subscription_access:991",
      "kind": "subscription_access",
      "state": "active",
      "customer_id": 314,
      "subject": {
        "type": "product_variant",
        "id": 84,
        "name": "Design kit — monthly"
      }
    }
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/customers/external/{externalId}/entitlements

List customer entitlements

Unified access without raw keys, serials, files, dynamic payloads, or seller-only metadata. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.entitlements.listCustomerEntitlementsByExternalId({
  "externalId": "externalId_01K4CUSTOMER"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.entitlements.list_customer_entitlements_by_external_id(external_id="externalId_01K4CUSTOMER")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->entitlements()->listCustomerEntitlementsByExternalId(externalId: 'externalId_01K4CUSTOMER');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Entitlements().ListCustomerEntitlementsByExternalID(context.Background(), "externalId_01K4CUSTOMER")
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Entitlements.ListCustomerEntitlementsByExternalIdAsync("externalId_01K4CUSTOMER");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.entitlements.listCustomerEntitlementsByExternalId(externalId = "externalId_01K4CUSTOMER")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.entitlements.list_customer_entitlements_by_external_id(external_id: "externalId_01K4CUSTOMER")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::entitlements::ListCustomerEntitlementsByExternalIdParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListCustomerEntitlementsByExternalIdParams::default();
    let result = client.entitlements().list_customer_entitlements_by_external_id("externalId_01K4CUSTOMER", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Entitlements.list_customer_entitlements_by_external_id(client, "externalId_01K4CUSTOMER")
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp entitlements list-customer-entitlements-by-external-id externalId_01K4CUSTOMER

```

- Method: `GET`

- Path: `/v2/customers/external/{externalId}/entitlements`

- Full URL: `https://sell.app/api/v2/customers/external/{externalId}/entitlements`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_EXTERNAL_ID='externalId_01K4CUSTOMER'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/customers/external/${SELLAPP_EXTERNAL_ID}/entitlements" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `externalId` (`string`, required): The externalId identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "state",
          "customer_id",
          "subject"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z_]+:[A-Za-z0-9-]+$"
          },
          "kind": {
            "type": "string",
            "enum": [
              "delivered_product",
              "license",
              "community_grant",
              "booking",
              "subscription_access"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "suspended",
              "expired",
              "revoked",
              "failed",
              "action_required"
            ]
          },
          "customer_id": {
            "type": "integer"
          },
          "subject": {
            "type": "object",
            "required": [
              "type",
              "id",
              "name"
            ],
            "properties": {
              "type": {
                "type": "string"
              },
              "id": {
                "type": [
                  "integer",
                  "string"
                ]
              },
              "name": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "id": "subscription_access:991",
      "kind": "subscription_access",
      "state": "active",
      "customer_id": 314,
      "subject": {
        "type": "product_variant",
        "id": 84,
        "name": "Design kit — monthly"
      }
    }
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Customers (/docs/api/customers)



Use customer endpoints to connect an email address with its purchase history in your store. Use an API key with the `invoice` ability or OAuth with `orders:read` for reads and `orders:write` for mutations. Send the store slug in `X-STORE`. The account must also have invoice access for that store.

The API returns the customer's email because it is the store-specific purchase identity. Checkout IP addresses, billing details, location, and community account identifiers are intentionally excluded. Revenue is returned as `insights.revenue_usd_cents`.

Wallet status and balance are omitted unless both the token and staff role have wallet or store management permission. When included, `wallet.balance_cents` uses integer USD cents.


# List customers (/docs/api/customers/list-customers)

## GET /v2/customers

List customers

List customer profiles for the authenticated store. Requires the `invoice` Sanctum ability and matching store permission. Responses deliberately redact checkout IP, billing, location, and community identity data. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.customers.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.customers.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->customers()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CustomersListParams{}
    page := client.Customers().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Customers.ListAsync(new CustomersListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.customers.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.customers.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customers::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.customers().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Customers.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customers list

```

- Method: `GET`

- Path: `/v2/customers`

- Full URL: `https://sell.app/api/v2/customers`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/customers" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching customers without pagination metadata.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "A store-scoped customer profile. Checkout IP, billing, location, and community identity data are intentionally excluded.",
            "required": [
              "id",
              "email",
              "external_id",
              "name",
              "locale",
              "metadata",
              "insights",
              "created_at",
              "updated_at"
            ],
            "properties": {
              "id": {
                "type": "integer",
                "example": 125
              },
              "email": {
                "type": "string",
                "format": "email",
                "description": "The customer's store-specific purchase identity. Treat this value as personal data.",
                "example": "maya.chen@example.com"
              },
              "external_id": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 255
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 255
              },
              "locale": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 35
              },
              "metadata": {
                "type": "object",
                "additionalProperties": true
              },
              "insights": {
                "type": "object",
                "required": [
                  "orders_count",
                  "line_items_count",
                  "completed_line_items_count",
                  "pending_line_items_count",
                  "voided_line_items_count",
                  "subscriptions_count",
                  "revenue_usd_cents",
                  "first_purchase_at",
                  "last_purchase_at",
                  "favorite_payment_method"
                ],
                "properties": {
                  "orders_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 3
                  },
                  "line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 4
                  },
                  "completed_line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 3
                  },
                  "pending_line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 1
                  },
                  "voided_line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 0
                  },
                  "subscriptions_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 1
                  },
                  "revenue_usd_cents": {
                    "type": "integer",
                    "description": "Completed line-item revenue in integer USD minor units.",
                    "example": 10900
                  },
                  "first_purchase_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "last_purchase_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "favorite_payment_method": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The most frequently used line-item payment method.",
                    "example": "STRIPE"
                  }
                }
              },
              "wallet": {
                "description": "Wallet status and balance. Omitted unless the token and staff role have wallet or store management permission.",
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "type": "object",
                    "required": [
                      "status",
                      "balance_cents"
                    ],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": [
                          "active",
                          "frozen"
                        ]
                      },
                      "balance_cents": {
                        "type": "integer",
                        "minimum": 0,
                        "description": "Current wallet balance in integer USD minor units.",
                        "example": 2500
                      }
                    }
                  }
                ]
              },
              "created_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "updated_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "A store-scoped customer profile. Checkout IP, billing, location, and community identity data are intentionally excluded.",
            "required": [
              "id",
              "email",
              "external_id",
              "name",
              "locale",
              "metadata",
              "insights",
              "created_at",
              "updated_at"
            ],
            "properties": {
              "id": {
                "type": "integer",
                "example": 125
              },
              "email": {
                "type": "string",
                "format": "email",
                "description": "The customer's store-specific purchase identity. Treat this value as personal data.",
                "example": "maya.chen@example.com"
              },
              "external_id": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 255
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 255
              },
              "locale": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 35
              },
              "metadata": {
                "type": "object",
                "additionalProperties": true
              },
              "insights": {
                "type": "object",
                "required": [
                  "orders_count",
                  "line_items_count",
                  "completed_line_items_count",
                  "pending_line_items_count",
                  "voided_line_items_count",
                  "subscriptions_count",
                  "revenue_usd_cents",
                  "first_purchase_at",
                  "last_purchase_at",
                  "favorite_payment_method"
                ],
                "properties": {
                  "orders_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 3
                  },
                  "line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 4
                  },
                  "completed_line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 3
                  },
                  "pending_line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 1
                  },
                  "voided_line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 0
                  },
                  "subscriptions_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 1
                  },
                  "revenue_usd_cents": {
                    "type": "integer",
                    "description": "Completed line-item revenue in integer USD minor units.",
                    "example": 10900
                  },
                  "first_purchase_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "last_purchase_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "favorite_payment_method": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The most frequently used line-item payment method.",
                    "example": "STRIPE"
                  }
                }
              },
              "wallet": {
                "description": "Wallet status and balance. Omitted unless the token and staff role have wallet or store management permission.",
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "type": "object",
                    "required": [
                      "status",
                      "balance_cents"
                    ],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": [
                          "active",
                          "frozen"
                        ]
                      },
                      "balance_cents": {
                        "type": "integer",
                        "minimum": 0,
                        "description": "Current wallet balance in integer USD minor units.",
                        "example": 2500
                      }
                    }
                  }
                ]
              },
              "created_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "updated_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 125,
      "email": "maya.chen@example.com",
      "external_id": null,
      "name": null,
      "locale": null,
      "metadata": {},
      "insights": {
        "orders_count": 3,
        "line_items_count": 4,
        "completed_line_items_count": 3,
        "pending_line_items_count": 1,
        "voided_line_items_count": 0,
        "subscriptions_count": 1,
        "revenue_usd_cents": 10900,
        "first_purchase_at": "2026-06-10T13:15:00.000000Z",
        "last_purchase_at": "2026-07-10T13:15:00.000000Z",
        "favorite_payment_method": "STRIPE"
      },
      "wallet": {
        "status": "active",
        "balance_cents": 2500
      },
      "created_at": "2026-06-10T13:15:00.000000Z",
      "updated_at": "2026-07-10T13:15:00.000000Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/customers?page=1",
    "last": "https://sell.app/api/v2/customers?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/customers",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/customers?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve a customer (/docs/api/customers/retrieve-customer)

## GET /v2/customers/{customer}

Retrieve a customer

Retrieve a store-scoped customer profile and concise order, line-item, subscription, and revenue insights. Wallet insights are included only when the token and staff role also have wallet or store management permission. Requires the `invoice` Sanctum ability and matching store permission. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.customers.get({
  "customer": 125
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.customers.get(customer=125)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->customers()->get(customer: 125);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Customers().Get(context.Background(), 125)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Customers.GetAsync("125");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.customers.get(customer = "125")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.customers.get(customer: 125)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customers::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.customers().get("125", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Customers.get(client, 125)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customers get 125

```

- Method: `GET`

- Path: `/v2/customers/{customer}`

- Full URL: `https://sell.app/api/v2/customers/{customer}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_CUSTOMER_ID='125'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/customers/${SELLAPP_CUSTOMER_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `customer` (`integer`, required): The customer path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "description": "A store-scoped customer profile. Checkout IP, billing, location, and community identity data are intentionally excluded.",
      "required": [
        "id",
        "email",
        "external_id",
        "name",
        "locale",
        "metadata",
        "insights",
        "created_at",
        "updated_at"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "example": 125
        },
        "email": {
          "type": "string",
          "format": "email",
          "description": "The customer's store-specific purchase identity. Treat this value as personal data.",
          "example": "maya.chen@example.com"
        },
        "external_id": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "name": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        },
        "locale": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 35
        },
        "metadata": {
          "type": "object",
          "additionalProperties": true
        },
        "insights": {
          "type": "object",
          "required": [
            "orders_count",
            "line_items_count",
            "completed_line_items_count",
            "pending_line_items_count",
            "voided_line_items_count",
            "subscriptions_count",
            "revenue_usd_cents",
            "first_purchase_at",
            "last_purchase_at",
            "favorite_payment_method"
          ],
          "properties": {
            "orders_count": {
              "type": "integer",
              "minimum": 0,
              "example": 3
            },
            "line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 4
            },
            "completed_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 3
            },
            "pending_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 1
            },
            "voided_line_items_count": {
              "type": "integer",
              "minimum": 0,
              "example": 0
            },
            "subscriptions_count": {
              "type": "integer",
              "minimum": 0,
              "example": 1
            },
            "revenue_usd_cents": {
              "type": "integer",
              "description": "Completed line-item revenue in integer USD minor units.",
              "example": 10900
            },
            "first_purchase_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "last_purchase_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "favorite_payment_method": {
              "type": [
                "string",
                "null"
              ],
              "description": "The most frequently used line-item payment method.",
              "example": "STRIPE"
            }
          }
        },
        "wallet": {
          "description": "Wallet status and balance. Omitted unless the token and staff role have wallet or store management permission.",
          "oneOf": [
            {
              "type": "null"
            },
            {
              "type": "object",
              "required": [
                "status",
                "balance_cents"
              ],
              "properties": {
                "status": {
                  "type": "string",
                  "enum": [
                    "active",
                    "frozen"
                  ]
                },
                "balance_cents": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Current wallet balance in integer USD minor units.",
                  "example": 2500
                }
              }
            }
          ]
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 125,
    "email": "maya.chen@example.com",
    "external_id": null,
    "name": null,
    "locale": null,
    "metadata": {},
    "insights": {
      "orders_count": 3,
      "line_items_count": 4,
      "completed_line_items_count": 3,
      "pending_line_items_count": 1,
      "voided_line_items_count": 0,
      "subscriptions_count": 1,
      "revenue_usd_cents": 10900,
      "first_purchase_at": "2026-06-10T13:15:00.000000Z",
      "last_purchase_at": "2026-07-10T13:15:00.000000Z",
      "favorite_payment_method": "STRIPE"
    },
    "wallet": {
      "status": "active",
      "balance_cents": 2500
    },
    "created_at": "2026-06-10T13:15:00.000000Z",
    "updated_at": "2026-07-10T13:15:00.000000Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Search customers (/docs/api/customers/search-customers)

## POST /v2/customers/search

Search customers

Search customer email identities and compose supported ID or email filters and deterministic sorts. Requires the `invoice` Sanctum ability and matching store permission. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.customers.search({
  "filters": [{"field": "id", "operator": "=", "value": 125}],
  "sort": [{"field": "created_at", "direction": "desc"}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.customers.search(
    filters=[{"field": "id", "operator": "=", "value": 125}],
    sort=[{"field": "created_at", "direction": "desc"}]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->customers()->search(
    filters: [['field' => 'id', 'operator' => '=', 'value' => 125]],
    sort: [['field' => 'created_at', 'direction' => 'desc']],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.CustomersSearchParams{}
    if err := json.Unmarshal([]byte("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":125}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}"), params); err != nil { panic(err) }
    page := client.Customers().Search(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Customers.SearchAsync(new CustomersSearchOptions
    {
        Filters = JsonConvert.DeserializeObject<List<SearchCustomersRequestApplicationJsonPropertyFiltersItem>>("[{\"field\":\"id\",\"operator\":\"=\",\"value\":125}]")!,
        Sort = JsonConvert.DeserializeObject<List<SearchCustomersRequestApplicationJsonPropertySortItem>>("[{\"field\":\"created_at\",\"direction\":\"desc\"}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.customers.search(filters = listOf(ObjectMapperFactory.read("{\"field\":\"id\",\"operator\":\"=\",\"value\":125}", app.sell.sellapp.models.SearchCustomersRequestApplicationJsonPropertyFiltersItem::class.java)), sort = listOf(ObjectMapperFactory.read("{\"field\":\"created_at\",\"direction\":\"desc\"}", app.sell.sellapp.models.SearchCustomersRequestApplicationJsonPropertySortItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.customers.search(
  filters: [{ field: "id", operator: "=", value: 125 }],
  sort: [{ field: "created_at", direction: "desc" }]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::customers::SearchParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = SearchParams::new(serde_json::from_str("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":125}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}")?);
    let result = client.customers().search(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Customers.search(client, %{"filters" => [%{"field" => "id", "operator" => "=", "value" => 125}], "sort" => [%{"field" => "created_at", "direction" => "desc"}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp customers search --body '{"filters":[{"field":"id","operator":"=","value":125}],"sort":[{"field":"created_at","direction":"desc"}]}'

```

- Method: `POST`

- Path: `/v2/customers/search`

- Full URL: `https://sell.app/api/v2/customers/search`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/customers/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 125
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.
- `pagination` (`boolean`, optional): Set to false to return at most 100 matching customers without pagination metadata.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "field",
          "value"
        ],
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "id",
              "email",
              "external_id",
              "locale"
            ]
          },
          "operator": {
            "type": "string",
            "enum": [
              "=",
              "!=",
              "<>",
              "<",
              "<=",
              ">",
              ">=",
              "like",
              "not like"
            ],
            "default": "="
          },
          "value": {},
          "type": false,
          "nested": false
        }
      }
    },
    "sort": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "id",
              "email",
              "created_at",
              "updated_at"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "default": "asc"
          }
        },
        "required": [
          "field"
        ]
      }
    },
    "search": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 255
        }
      }
    },
    "includes": {
      "type": "array",
      "maxItems": 0,
      "items": {
        "type": "object"
      }
    }
  }
}
```

Example:

```json
{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 125
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "A store-scoped customer profile. Checkout IP, billing, location, and community identity data are intentionally excluded.",
            "required": [
              "id",
              "email",
              "external_id",
              "name",
              "locale",
              "metadata",
              "insights",
              "created_at",
              "updated_at"
            ],
            "properties": {
              "id": {
                "type": "integer",
                "example": 125
              },
              "email": {
                "type": "string",
                "format": "email",
                "description": "The customer's store-specific purchase identity. Treat this value as personal data.",
                "example": "maya.chen@example.com"
              },
              "external_id": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 255
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 255
              },
              "locale": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 35
              },
              "metadata": {
                "type": "object",
                "additionalProperties": true
              },
              "insights": {
                "type": "object",
                "required": [
                  "orders_count",
                  "line_items_count",
                  "completed_line_items_count",
                  "pending_line_items_count",
                  "voided_line_items_count",
                  "subscriptions_count",
                  "revenue_usd_cents",
                  "first_purchase_at",
                  "last_purchase_at",
                  "favorite_payment_method"
                ],
                "properties": {
                  "orders_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 3
                  },
                  "line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 4
                  },
                  "completed_line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 3
                  },
                  "pending_line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 1
                  },
                  "voided_line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 0
                  },
                  "subscriptions_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 1
                  },
                  "revenue_usd_cents": {
                    "type": "integer",
                    "description": "Completed line-item revenue in integer USD minor units.",
                    "example": 10900
                  },
                  "first_purchase_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "last_purchase_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "favorite_payment_method": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The most frequently used line-item payment method.",
                    "example": "STRIPE"
                  }
                }
              },
              "wallet": {
                "description": "Wallet status and balance. Omitted unless the token and staff role have wallet or store management permission.",
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "type": "object",
                    "required": [
                      "status",
                      "balance_cents"
                    ],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": [
                          "active",
                          "frozen"
                        ]
                      },
                      "balance_cents": {
                        "type": "integer",
                        "minimum": 0,
                        "description": "Current wallet balance in integer USD minor units.",
                        "example": 2500
                      }
                    }
                  }
                ]
              },
              "created_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "updated_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          }
        },
        "links": {
          "type": "object",
          "required": [
            "first",
            "last",
            "prev",
            "next"
          ],
          "properties": {
            "first": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=1"
            },
            "last": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists?page=4"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "example": null
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "example": "https://sell.app/api/v1/blacklists?page=2"
            }
          }
        },
        "meta": {
          "type": "object",
          "required": [
            "current_page",
            "from",
            "last_page",
            "links",
            "path",
            "per_page",
            "to",
            "total"
          ],
          "properties": {
            "current_page": {
              "type": "integer",
              "example": 1
            },
            "from": {
              "type": [
                "integer",
                "null"
              ],
              "example": 1
            },
            "last_page": {
              "type": "integer",
              "example": 4
            },
            "links": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "url",
                  "label",
                  "active"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            },
            "path": {
              "type": "string",
              "example": "https://sell.app/api/v1/blacklists"
            },
            "per_page": {
              "type": "integer",
              "example": 15
            },
            "to": {
              "type": [
                "integer",
                "null"
              ],
              "example": 15
            },
            "total": {
              "type": "integer",
              "example": 57
            }
          }
        }
      },
      "required": [
        "data",
        "links",
        "meta"
      ]
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "A store-scoped customer profile. Checkout IP, billing, location, and community identity data are intentionally excluded.",
            "required": [
              "id",
              "email",
              "external_id",
              "name",
              "locale",
              "metadata",
              "insights",
              "created_at",
              "updated_at"
            ],
            "properties": {
              "id": {
                "type": "integer",
                "example": 125
              },
              "email": {
                "type": "string",
                "format": "email",
                "description": "The customer's store-specific purchase identity. Treat this value as personal data.",
                "example": "maya.chen@example.com"
              },
              "external_id": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 255
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 255
              },
              "locale": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 35
              },
              "metadata": {
                "type": "object",
                "additionalProperties": true
              },
              "insights": {
                "type": "object",
                "required": [
                  "orders_count",
                  "line_items_count",
                  "completed_line_items_count",
                  "pending_line_items_count",
                  "voided_line_items_count",
                  "subscriptions_count",
                  "revenue_usd_cents",
                  "first_purchase_at",
                  "last_purchase_at",
                  "favorite_payment_method"
                ],
                "properties": {
                  "orders_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 3
                  },
                  "line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 4
                  },
                  "completed_line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 3
                  },
                  "pending_line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 1
                  },
                  "voided_line_items_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 0
                  },
                  "subscriptions_count": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 1
                  },
                  "revenue_usd_cents": {
                    "type": "integer",
                    "description": "Completed line-item revenue in integer USD minor units.",
                    "example": 10900
                  },
                  "first_purchase_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "last_purchase_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "favorite_payment_method": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The most frequently used line-item payment method.",
                    "example": "STRIPE"
                  }
                }
              },
              "wallet": {
                "description": "Wallet status and balance. Omitted unless the token and staff role have wallet or store management permission.",
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "type": "object",
                    "required": [
                      "status",
                      "balance_cents"
                    ],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": [
                          "active",
                          "frozen"
                        ]
                      },
                      "balance_cents": {
                        "type": "integer",
                        "minimum": 0,
                        "description": "Current wallet balance in integer USD minor units.",
                        "example": 2500
                      }
                    }
                  }
                ]
              },
              "created_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "updated_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          }
        }
      },
      "required": [
        "data"
      ]
    }
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 125,
      "email": "maya.chen@example.com",
      "external_id": null,
      "name": null,
      "locale": null,
      "metadata": {},
      "insights": {
        "orders_count": 3,
        "line_items_count": 4,
        "completed_line_items_count": 3,
        "pending_line_items_count": 1,
        "voided_line_items_count": 0,
        "subscriptions_count": 1,
        "revenue_usd_cents": 10900,
        "first_purchase_at": "2026-06-10T13:15:00.000000Z",
        "last_purchase_at": "2026-07-10T13:15:00.000000Z",
        "favorite_payment_method": "STRIPE"
      },
      "wallet": {
        "status": "active",
        "balance_cents": 2500
      },
      "created_at": "2026-06-10T13:15:00.000000Z",
      "updated_at": "2026-07-10T13:15:00.000000Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/customers/search?page=1",
    "last": "https://sell.app/api/v2/customers/search?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/customers/search",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/customers/search?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Disputes (/docs/api/disputes)

Read dispute status and provider identifiers to match a case with your payment
provider's records. Disputes can concern an order or a standalone charge, so the
collection is available independently of orders. These endpoints do not submit
evidence or change the dispute.

Raw provider payloads and evidence are excluded. The API currently reports an
unrecognized provider dispute status as `open`; do not assume every provider
state has a distinct SellApp status. Check the provider's records when needed.

## GET /v2/disputes

List disputes

Read-only, redacted, store-scoped disputes that may reference an Order or Charge. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.disputes.listDisputes();
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.disputes.list_disputes()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->disputes()->listDisputes();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    page := client.Disputes().List(context.Background())
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Disputes.ListAsync();
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.disputes.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.disputes.list_disputes
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::disputes::ListDisputesParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListDisputesParams::default();
    let result = client.disputes().list_disputes(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Disputes.list_disputes(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp disputes list-disputes

```

- Method: `GET`

- Path: `/v2/disputes`

- Full URL: `https://sell.app/api/v2/disputes`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/disputes" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data",
    "links",
    "meta"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "source",
          "provider",
          "amount",
          "currency",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "source": {
            "type": "object",
            "required": [
              "type",
              "id"
            ],
            "properties": {
              "type": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "order",
                  "charge",
                  null
                ]
              },
              "id": {
                "type": "integer"
              }
            }
          },
          "provider": {
            "type": "string"
          },
          "provider_dispute_id": {
            "type": "string"
          },
          "amount": {
            "type": "integer"
          },
          "currency": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "under_review",
              "won",
              "lost",
              "closed"
            ]
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "id": "01992b10-a7d2-7b91-9822-32e8d7454e7c",
      "source": {
        "type": "order",
        "id": 4242
      },
      "provider": "stripe",
      "provider_dispute_id": "dp_example",
      "amount": 2900,
      "currency": "usd",
      "status": "under_review",
      "reason": "product_not_received"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/disputes?page=1",
    "last": "https://sell.app/api/v2/disputes?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/disputes",
    "per_page": 20,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/disputes?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/disputes/{dispute}

Retrieve a dispute

Retrieve one redacted dispute. No dispute mutations are exposed. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.disputes.getDispute({
  "dispute": "01992b10-a7d2-7b91-9822-32e8d7454e7c"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.disputes.get_dispute(dispute="01992b10-a7d2-7b91-9822-32e8d7454e7c")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->disputes()->getDispute(dispute: '01992b10-a7d2-7b91-9822-32e8d7454e7c');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Disputes().Get(context.Background(), "01992b10-a7d2-7b91-9822-32e8d7454e7c")
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Disputes.GetAsync("01992b10-a7d2-7b91-9822-32e8d7454e7c");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.disputes.get(dispute = "01992b10-a7d2-7b91-9822-32e8d7454e7c")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.disputes.get_dispute(dispute: "01992b10-a7d2-7b91-9822-32e8d7454e7c")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::disputes::GetDisputeParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetDisputeParams::default();
    let result = client.disputes().get_dispute("01992b10-a7d2-7b91-9822-32e8d7454e7c", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Disputes.get_dispute(client, "01992b10-a7d2-7b91-9822-32e8d7454e7c")
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp disputes get-dispute 01992b10-a7d2-7b91-9822-32e8d7454e7c

```

- Method: `GET`

- Path: `/v2/disputes/{dispute}`

- Full URL: `https://sell.app/api/v2/disputes/{dispute}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_DISPUTE_ID='01992b10-a7d2-7b91-9822-32e8d7454e7c'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/disputes/${SELLAPP_DISPUTE_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `dispute` (`string`, required): The dispute identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "source",
        "provider",
        "amount",
        "currency",
        "status"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "source": {
          "type": "object",
          "required": [
            "type",
            "id"
          ],
          "properties": {
            "type": {
              "type": [
                "string",
                "null"
              ],
              "enum": [
                "order",
                "charge",
                null
              ]
            },
            "id": {
              "type": "integer"
            }
          }
        },
        "provider": {
          "type": "string"
        },
        "provider_dispute_id": {
          "type": "string"
        },
        "amount": {
          "type": "integer"
        },
        "currency": {
          "type": "string"
        },
        "status": {
          "type": "string",
          "enum": [
            "open",
            "under_review",
            "won",
            "lost",
            "closed"
          ]
        },
        "reason": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": "01992b10-a7d2-7b91-9822-32e8d7454e7c",
    "source": {
      "type": "order",
      "id": 4242
    },
    "provider": "stripe",
    "provider_dispute_id": "dp_example",
    "amount": 2900,
    "currency": "usd",
    "status": "under_review",
    "reason": "product_not_received"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Events and delivery history (/docs/api/events)

Read recorded integration events to recover notifications your application
missed. Events remain available for 30 days. Read with `GET`, save the returned
`meta.next_cursor`, and pass it into the next request. Empty pages are normal:
wait longer between repeated empty reads, then poll again.

The event envelope identifies the event, its type and time, and the referenced
resource. `order.completed` has a detailed, limited set of purchase fields.
Other event types may have an empty `data` object. Retrieve the referenced
resource when you need its current details; the event history is not a complete
historical copy of every resource.

Signed cursors are tied to the selected store and exact filter set, so do not reuse a cursor with different filters. An expired cursor returns `410 cursor_expired` with `fallback.transport: "cursor_polling"`; restart without the expired cursor.

Delivery replay sends a retained integration event to its configured webhook
destination again. It creates a new delivery ID and keeps the original
integration-event ID. It does not repeat the purchase, refund, or other business
action. You cannot supply a different destination URL, payload, or query override.

## GET /v2/events

List integration events

Poll the 30-day journal with signed, filter-bound cursors. Use client-controlled backoff between ordinary requests. An expired position returns 410 cursor_expired with cursor_polling guidance. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.events.listIntegrationEvents({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.events.list_integration_events()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->events()->listIntegrationEvents();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.EventsListIntegrationEventsParams{}
    page := client.Events().ListIntegrationEvents(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Events.ListIntegrationEventsAsync(new EventsListIntegrationEventsOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.events.listIntegrationEvents()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.events.list_integration_events
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::events::ListIntegrationEventsParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListIntegrationEventsParams::default();
    let result = client.events().list_integration_events(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Events.list_integration_events(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp events list-integration-events

```

- Method: `GET`

- Path: `/v2/events`

- Full URL: `https://sell.app/api/v2/events`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/events" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `cursor` (`string`, optional): Signed cursor bound to this filter set.
- `limit` (`integer`, optional): Maximum events to return.
- `type` (`string`, optional): Return only this event type.
- `subject_type` (`string`, optional): Return events for this subject type.
- `subject_id` (`string`, optional): Return events for this subject identifier.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data",
    "meta"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "type",
          "version",
          "store_id",
          "occurred_at",
          "subject",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_"
          },
          "type": {
            "type": "string"
          },
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "store_id": {
            "type": "string"
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time"
          },
          "subject": {
            "type": "object",
            "required": [
              "type",
              "id"
            ],
            "properties": {
              "type": {
                "type": "string"
              },
              "id": {
                "type": "string"
              }
            }
          },
          "data": {
            "type": "object",
            "maxProperties": 100,
            "additionalProperties": {
              "oneOf": [
                {
                  "type": "string",
                  "maxLength": 500
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ]
            }
          }
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "next_cursor",
        "has_more",
        "retention_days"
      ],
      "properties": {
        "next_cursor": {
          "type": "string"
        },
        "has_more": {
          "type": "boolean"
        },
        "retention_days": {
          "type": "integer",
          "enum": [
            30
          ]
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "id": "evt_01K4CUSTOMER",
      "type": "order.completed",
      "version": 1,
      "store_id": "12",
      "occurred_at": "2026-09-04T09:12:00Z",
      "subject": {
        "type": "order",
        "id": "4242"
      },
      "data": {
        "total_cents": 2900,
        "currency": "USD"
      }
    }
  ],
  "meta": {
    "next_cursor": "cur_signed_filter_bound_01K4",
    "has_more": false,
    "retention_days": 30
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor points outside the 30-day retention window. Restart ordinary cursor polling without it.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "message",
    "type",
    "code",
    "status",
    "fallback"
  ],
  "properties": {
    "message": {
      "type": "string"
    },
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error"
      ]
    },
    "code": {
      "type": "string",
      "enum": [
        "cursor_expired"
      ]
    },
    "status": {
      "type": "integer",
      "enum": [
        410
      ]
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
```

Example:

```json
{
  "message": "The event cursor is outside the 30-day retention window.",
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "status": 410,
  "fallback": {
    "transport": "cursor_polling",
    "url": "https://sell.app/api/v2/events"
  }
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/orders/{order}/events

List order events

Read retained events for this order. Use the returned cursor for the next request and wait between polls. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.events.listOrderEvents({
  "order": 42
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.events.list_order_events(order=42)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->events()->listOrderEvents(order: 42);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.EventsListOrderEventsParams{}
    page := client.Events().ListOrderEvents(context.Background(), 42, params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Events.ListOrderEventsAsync(
    "42",
    new EventsListOrderEventsOptions
    {
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.events.listOrderEvents(order = "42")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.events.list_order_events(order: 42)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::events::ListOrderEventsParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListOrderEventsParams::default();
    let result = client.events().list_order_events("42", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Events.list_order_events(client, 42, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp events list-order-events 42

```

- Method: `GET`

- Path: `/v2/orders/{order}/events`

- Full URL: `https://sell.app/api/v2/orders/{order}/events`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_ORDER_ID='42'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/orders/${SELLAPP_ORDER_ID}/events" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `order` (`integer`, required): The order identifier.

## Query Parameters
- `cursor` (`string`, optional): Signed cursor bound to this filter set.
- `limit` (`integer`, optional): Maximum events to return.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data",
    "meta"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "type",
          "version",
          "store_id",
          "occurred_at",
          "subject",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_"
          },
          "type": {
            "type": "string"
          },
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "store_id": {
            "type": "string"
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time"
          },
          "subject": {
            "type": "object",
            "required": [
              "type",
              "id"
            ],
            "properties": {
              "type": {
                "type": "string"
              },
              "id": {
                "type": "string"
              }
            }
          },
          "data": {
            "type": "object",
            "maxProperties": 100,
            "additionalProperties": {
              "oneOf": [
                {
                  "type": "string",
                  "maxLength": 500
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ]
            }
          }
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "next_cursor",
        "has_more",
        "retention_days"
      ],
      "properties": {
        "next_cursor": {
          "type": "string"
        },
        "has_more": {
          "type": "boolean"
        },
        "retention_days": {
          "type": "integer",
          "enum": [
            30
          ]
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "id": "evt_01K4CUSTOMER",
      "type": "order.completed",
      "version": 1,
      "store_id": "12",
      "occurred_at": "2026-09-04T09:12:00Z",
      "subject": {
        "type": "order",
        "id": "4242"
      },
      "data": {
        "total_cents": 2900,
        "currency": "USD"
      }
    }
  ],
  "meta": {
    "next_cursor": "cur_signed_filter_bound_01K4",
    "has_more": false,
    "retention_days": 30
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor points outside the 30-day retention window. Restart ordinary cursor polling without it.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "message",
    "type",
    "code",
    "status",
    "fallback"
  ],
  "properties": {
    "message": {
      "type": "string"
    },
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error"
      ]
    },
    "code": {
      "type": "string",
      "enum": [
        "cursor_expired"
      ]
    },
    "status": {
      "type": "integer",
      "enum": [
        410
      ]
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
```

Example:

```json
{
  "message": "The event cursor is outside the 30-day retention window.",
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "status": 410,
  "fallback": {
    "transport": "cursor_polling",
    "url": "https://sell.app/api/v2/events"
  }
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/webhook-event-types

List webhook event types

List versioned outbound event types. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.webhookPlatform.listWebhookEventTypes();
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.webhook_platform.list_webhook_event_types()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->webhookPlatform()->listWebhookEventTypes();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.WebhookPlatform().ListEventTypes(context.Background())
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.WebhookPlatform.ListEventTypesAsync();
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.webhookPlatform.listEventTypes()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.webhook_platform.list_webhook_event_types
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::webhook_platform::ListWebhookEventTypesParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListWebhookEventTypesParams::default();
    let result = client.webhook_platform().list_webhook_event_types(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.WebhookPlatform.list_webhook_event_types(client)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp webhook-platform list-webhook-event-types

```

- Method: `GET`

- Path: `/v2/webhook-event-types`

- Full URL: `https://sell.app/api/v2/webhook-event-types`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `webhooks:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/webhook-event-types" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "type",
          "version",
          "description"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "version": {
            "type": "integer"
          },
          "description": {
            "type": "string"
          }
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "type": "order.completed",
      "version": 1,
      "description": "An order completed and delivery began."
    }
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/webhook-deliveries

List webhook deliveries

Destination origin only; response bodies are redacted and capped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.webhookPlatform.listWebhookDeliveries();
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.webhook_platform.list_webhook_deliveries()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->webhookPlatform()->listWebhookDeliveries();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    page := client.WebhookPlatform().ListDeliveries(context.Background())
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.WebhookPlatform.ListDeliveriesAsync();
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.webhookPlatform.listDeliveries()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.webhook_platform.list_webhook_deliveries
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::webhook_platform::ListWebhookDeliveriesParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListWebhookDeliveriesParams::default();
    let result = client.webhook_platform().list_webhook_deliveries(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.WebhookPlatform.list_webhook_deliveries(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp webhook-platform list-webhook-deliveries

```

- Method: `GET`

- Path: `/v2/webhook-deliveries`

- Full URL: `https://sell.app/api/v2/webhook-deliveries`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `webhooks:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/webhook-deliveries" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data",
    "links",
    "meta"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "event_id",
          "event_type",
          "status",
          "destination_origin",
          "attempts"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "event_id": {
            "type": "string",
            "pattern": "^evt_"
          },
          "event_type": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "delivering",
              "succeeded",
              "failed"
            ]
          },
          "destination_origin": {
            "type": "string",
            "format": "uri"
          },
          "attempts": {
            "type": "integer"
          },
          "response_status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "response_body": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2048
          }
        }
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "id": "01992b31-c8bd-75b5-b02d-6ae0aa418940",
      "event_id": "evt_01K4CUSTOMER",
      "event_type": "order.completed",
      "status": "succeeded",
      "destination_origin": "https://hooks.example.com",
      "attempts": 1,
      "response_status": 204,
      "response_body": null
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/webhook-deliveries?page=1",
    "last": "https://sell.app/api/v2/webhook-deliveries?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/webhook-deliveries",
    "per_page": 20,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/webhook-deliveries?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/webhook-deliveries/{delivery}

Retrieve a webhook delivery

Retrieve one redacted delivery. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.webhookPlatform.getWebhookDelivery({
  "delivery": "01992b31-c8bd-75b5-b02d-6ae0aa418940"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.webhook_platform.get_webhook_delivery(delivery="01992b31-c8bd-75b5-b02d-6ae0aa418940")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->webhookPlatform()->getWebhookDelivery(delivery: '01992b31-c8bd-75b5-b02d-6ae0aa418940');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.WebhookPlatform().GetDelivery(context.Background(), "01992b31-c8bd-75b5-b02d-6ae0aa418940")
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.WebhookPlatform.GetDeliveryAsync("01992b31-c8bd-75b5-b02d-6ae0aa418940");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.webhookPlatform.getDelivery(delivery = "01992b31-c8bd-75b5-b02d-6ae0aa418940")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.webhook_platform.get_webhook_delivery(delivery: "01992b31-c8bd-75b5-b02d-6ae0aa418940")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::webhook_platform::GetWebhookDeliveryParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetWebhookDeliveryParams::default();
    let result = client.webhook_platform().get_webhook_delivery("01992b31-c8bd-75b5-b02d-6ae0aa418940", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.WebhookPlatform.get_webhook_delivery(client, "01992b31-c8bd-75b5-b02d-6ae0aa418940")
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp webhook-platform get-webhook-delivery 01992b31-c8bd-75b5-b02d-6ae0aa418940

```

- Method: `GET`

- Path: `/v2/webhook-deliveries/{delivery}`

- Full URL: `https://sell.app/api/v2/webhook-deliveries/{delivery}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `webhooks:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_DELIVERY_ID='01992b31-c8bd-75b5-b02d-6ae0aa418940'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/webhook-deliveries/${SELLAPP_DELIVERY_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `delivery` (`string`, required): The delivery identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "event_id",
        "event_type",
        "status",
        "destination_origin",
        "attempts"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "event_id": {
          "type": "string",
          "pattern": "^evt_"
        },
        "event_type": {
          "type": "string"
        },
        "status": {
          "type": "string",
          "enum": [
            "pending",
            "delivering",
            "succeeded",
            "failed"
          ]
        },
        "destination_origin": {
          "type": "string",
          "format": "uri"
        },
        "attempts": {
          "type": "integer"
        },
        "response_status": {
          "type": [
            "integer",
            "null"
          ]
        },
        "response_body": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 2048
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": "01992b31-c8bd-75b5-b02d-6ae0aa418940",
    "event_id": "evt_01K4CUSTOMER",
    "event_type": "order.completed",
    "status": "succeeded",
    "destination_origin": "https://hooks.example.com",
    "attempts": 1,
    "response_status": 204,
    "response_body": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## POST /v2/webhook-deliveries/{delivery}/replay

Replay a webhook delivery

Accept no URL, payload, or query overrides. Resolve the current channel server-side, create a new delivery ID, retain the integration-event ID, and sign with a new timestamp. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.webhookPlatform.replayWebhookDelivery({
  "delivery": "delivery_01K4CUSTOMER"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.webhook_platform.replay_webhook_delivery(delivery="delivery_01K4CUSTOMER")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->webhookPlatform()->replayWebhookDelivery(delivery: 'delivery_01K4CUSTOMER');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.WebhookPlatformReplayDeliveryParams{}
    if err := json.Unmarshal([]byte("{}"), &params.Body); err != nil { panic(err) }
    result, err := client.WebhookPlatform().ReplayDelivery(context.Background(), "delivery_01K4CUSTOMER", params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.WebhookPlatform.ReplayDeliveryAsync("delivery_01K4CUSTOMER");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.webhookPlatform.replayDelivery(delivery = "delivery_01K4CUSTOMER")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.webhook_platform.replay_webhook_delivery(delivery: "delivery_01K4CUSTOMER")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::webhook_platform::ReplayWebhookDeliveryParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ReplayWebhookDeliveryParams::new(serde_json::from_str("{}")?);
    let result = client.webhook_platform().replay_webhook_delivery("delivery_01K4CUSTOMER", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.WebhookPlatform.replay_webhook_delivery(client, "delivery_01K4CUSTOMER", %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp webhook-platform replay-webhook-delivery delivery_01K4CUSTOMER --yes

```

- Method: `POST`

- Path: `/v2/webhook-deliveries/{delivery}/replay`

- Full URL: `https://sell.app/api/v2/webhook-deliveries/{delivery}/replay`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `webhooks:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_DELIVERY_ID='delivery_01K4CUSTOMER'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/webhook-deliveries/${SELLAPP_DELIVERY_ID}/replay" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Idempotency-Key: project-library-2026-09-04' \
  --header 'Content-Type: application/json' \
  --data-raw '{}'
```

## Path Parameters
- `delivery` (`string`, required): The delivery identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, required): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "maxProperties": 0,
  "additionalProperties": false
}
```

Example:

```json
{}
```

## Responses

### 201

Created.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "event_id",
        "event_type",
        "status",
        "destination_origin",
        "attempts"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "event_id": {
          "type": "string",
          "pattern": "^evt_"
        },
        "event_type": {
          "type": "string"
        },
        "status": {
          "type": "string",
          "enum": [
            "pending",
            "delivering",
            "succeeded",
            "failed"
          ]
        },
        "destination_origin": {
          "type": "string",
          "format": "uri"
        },
        "attempts": {
          "type": "integer"
        },
        "response_status": {
          "type": [
            "integer",
            "null"
          ]
        },
        "response_body": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 2048
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": "01992b42-a0d7-7dc9-817a-b721e07d2f50",
    "event_id": "evt_01K4CUSTOMER",
    "event_type": "order.completed",
    "status": "pending",
    "destination_origin": "https://hooks.example.com",
    "attempts": 0,
    "response_status": null,
    "response_body": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Overview (/docs/api/feedback)

Feedback records a customer's rating and sentiment for a completed purchase.
Replies are public, not internal notes. Check the sender's permission and keep
a record of who posted each reply.

Feedback belongs to the selected store. In v2, `product_id` identifies the
reviewed product and `order_id` identifies the purchase. Either can be `null`.
Use the operation reference for sentiment values, reply fields, and timestamps.

## Endpoints [#endpoints]

* [List feedback](/api/feedback/list-all-feedback)
* [Search feedback](/api/feedback/search-feedback)
* [Retrieve feedback](/api/feedback/retrieve-specific-feedback)
* [Reply to feedback](/api/feedback/reply-to-feedback)

## Additional endpoint reference [#additional-endpoint-reference]

## PUT /v2/feedback/{feedback}

Reply to feedback

Publish a seller reply to a customer's feedback. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.feedback.v2ReplaceFeedback({
  "feedback": 1,
  "reply": "Please contact support if you need help with your download."
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.feedback.v2_replace_feedback(
    feedback=1,
    reply="Please contact support if you need help with your download."
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->feedback()->v2ReplaceFeedback(
    feedback: 1,
    reply: 'Please contact support if you need help with your download.',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.FeedbackV2ReplaceFeedbackParams{}
    if err := json.Unmarshal([]byte("{\"reply\":\"Please contact support if you need help with your download.\"}"), params); err != nil { panic(err) }
    result, err := client.Feedback().V2ReplaceFeedback(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Feedback.V2ReplaceFeedbackAsync(
    "1",
    new FeedbackV2ReplaceFeedbackOptions
    {
        Reply = "Please contact support if you need help with your download.",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.feedback.v2ReplaceFeedback(feedback = "1", reply = "Please contact support if you need help with your download.")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.feedback.v2_replace_feedback(
  feedback: 1,
  reply: "Please contact support if you need help with your download."
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::feedback::V2ReplaceFeedbackParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2ReplaceFeedbackParams::new(serde_json::from_str("{\"reply\":\"Please contact support if you need help with your download.\"}")?);
    let result = client.feedback().v_2_replace_feedback("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Feedback.v2_replace_feedback(client, 1, %{"reply" => "Please contact support if you need help with your download."})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp feedback v-2-replace-feedback 1 --reply 'Please contact support if you need help with your download.' --yes

```

- Method: `PUT`

- Path: `/v2/feedback/{feedback}`

- Full URL: `https://sell.app/api/v2/feedback/{feedback}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `customers:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_FEEDBACK_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PUT \
  --url "${SELLAPP_API_BASE_URL}/v2/feedback/${SELLAPP_FEEDBACK_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "reply": "Please contact support if you need help with your download."
}'
```

## Path Parameters
- `feedback` (`integer`, required): The feedback path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "reply": {
      "type": "string"
    }
  },
  "required": [
    "reply"
  ]
}
```

Example:

```json
{
  "reply": "Please contact support if you need help with your download."
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "feedback": {
          "type": "string"
        },
        "rating": {
          "type": [
            "integer",
            "null"
          ]
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "metadata": {
          "type": "object",
          "additionalProperties": true
        },
        "message": {
          "type": [
            "string",
            "null"
          ]
        },
        "reply": {
          "type": [
            "string",
            "null"
          ]
        },
        "is_automatic": {
          "type": "boolean"
        },
        "product_id": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Product associated with the feedback, when available."
        },
        "order_id": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Purchase associated with the feedback, when available."
        },
        "sentiment": {
          "type": "string",
          "enum": [
            "POSITIVE",
            "NEUTRAL",
            "NEGATIVE"
          ]
        },
        "variant_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "product_title": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "id",
        "feedback",
        "rating",
        "deleted_at",
        "created_at",
        "updated_at",
        "store_id",
        "metadata",
        "message",
        "reply",
        "is_automatic",
        "product_id",
        "order_id",
        "sentiment",
        "variant_id",
        "product_title"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "feedback": "POSITIVE",
    "rating": 5,
    "deleted_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "metadata": {},
    "message": "The download arrived immediately and the setup instructions were clear.",
    "reply": "Please contact support if you need help with your download.",
    "is_automatic": true,
    "product_id": 1,
    "order_id": 1,
    "sentiment": "POSITIVE",
    "variant_id": null,
    "product_title": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# List all feedback (/docs/api/feedback/list-all-feedback)

List customer feedback for your store, 15 entries per page by default.

## GET /v2/feedback

List all feedback

List customer feedback for your store, 15 entries per page by default. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.feedback.v2ListFeedback({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.feedback.v2_list_feedback()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->feedback()->v2ListFeedback();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.FeedbackV2ListFeedbackParams{}
    page := client.Feedback().V2ListFeedback(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Feedback.V2ListFeedbackAsync(new FeedbackV2ListFeedbackOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.feedback.v2ListFeedback()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.feedback.v2_list_feedback
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::feedback::V2ListFeedbackParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2ListFeedbackParams::default();
    let result = client.feedback().v_2_list_feedback(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Feedback.v2_list_feedback(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp feedback v-2-list-feedback

```

- Method: `GET`

- Path: `/v2/feedback`

- Full URL: `https://sell.app/api/v2/feedback`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `customers:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/feedback" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "feedback": {
            "type": "string"
          },
          "rating": {
            "type": [
              "integer",
              "null"
            ]
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "message": {
            "type": [
              "string",
              "null"
            ]
          },
          "reply": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_automatic": {
            "type": "boolean"
          },
          "product_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Product associated with the feedback, when available."
          },
          "order_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Purchase associated with the feedback, when available."
          },
          "sentiment": {
            "type": "string",
            "enum": [
              "POSITIVE",
              "NEUTRAL",
              "NEGATIVE"
            ]
          },
          "variant_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "product_title": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "feedback",
          "rating",
          "deleted_at",
          "created_at",
          "updated_at",
          "store_id",
          "metadata",
          "message",
          "reply",
          "is_automatic",
          "product_id",
          "order_id",
          "sentiment",
          "variant_id",
          "product_title"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "feedback": "POSITIVE",
      "rating": 5,
      "deleted_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "metadata": {},
      "message": "The download arrived immediately and the setup instructions were clear.",
      "reply": "Thank you for your feedback.",
      "is_automatic": true,
      "product_id": 1,
      "order_id": 1,
      "sentiment": "POSITIVE",
      "variant_id": null,
      "product_title": null
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/feedback?page=1",
    "last": "https://sell.app/api/v2/feedback?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/feedback",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/feedback?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Reply to feedback (/docs/api/feedback/reply-to-feedback)

Publish a seller reply to a customer's feedback.

## PATCH /v2/feedback/{feedback}

Reply to feedback

Publish a seller reply to a customer's feedback. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.feedback.v2ReplyToFeedback({
  "feedback": 1,
  "reply": "Please contact support if you need help with your download."
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.feedback.v2_reply_to_feedback(
    feedback=1,
    reply="Please contact support if you need help with your download."
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->feedback()->v2ReplyToFeedback(
    feedback: 1,
    reply: 'Please contact support if you need help with your download.',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.FeedbackV2ReplyToFeedbackParams{}
    if err := json.Unmarshal([]byte("{\"reply\":\"Please contact support if you need help with your download.\"}"), params); err != nil { panic(err) }
    result, err := client.Feedback().V2ReplyToFeedback(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Feedback.V2ReplyToFeedbackAsync(
    "1",
    new FeedbackV2ReplyToFeedbackOptions
    {
        Reply = "Please contact support if you need help with your download.",
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.feedback.v2ReplyToFeedback(feedback = "1", reply = "Please contact support if you need help with your download.")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.feedback.v2_reply_to_feedback(
  feedback: 1,
  reply: "Please contact support if you need help with your download."
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::feedback::V2ReplyToFeedbackParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2ReplyToFeedbackParams::new(serde_json::from_str("{\"reply\":\"Please contact support if you need help with your download.\"}")?);
    let result = client.feedback().v_2_reply_to_feedback("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Feedback.v2_reply_to_feedback(client, 1, %{"reply" => "Please contact support if you need help with your download."})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp feedback v-2-reply-to-feedback 1 --reply 'Please contact support if you need help with your download.' --yes

```

- Method: `PATCH`

- Path: `/v2/feedback/{feedback}`

- Full URL: `https://sell.app/api/v2/feedback/{feedback}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `customers:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_FEEDBACK_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request PATCH \
  --url "${SELLAPP_API_BASE_URL}/v2/feedback/${SELLAPP_FEEDBACK_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "reply": "Please contact support if you need help with your download."
}'
```

## Path Parameters
- `feedback` (`integer`, required): The feedback path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "reply": {
      "type": "string"
    }
  },
  "required": [
    "reply"
  ]
}
```

Example:

```json
{
  "reply": "Please contact support if you need help with your download."
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "feedback": {
          "type": "string"
        },
        "rating": {
          "type": [
            "integer",
            "null"
          ]
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "metadata": {
          "type": "object",
          "additionalProperties": true
        },
        "message": {
          "type": [
            "string",
            "null"
          ]
        },
        "reply": {
          "type": [
            "string",
            "null"
          ]
        },
        "is_automatic": {
          "type": "boolean"
        },
        "product_id": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Product associated with the feedback, when available."
        },
        "order_id": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Purchase associated with the feedback, when available."
        },
        "sentiment": {
          "type": "string",
          "enum": [
            "POSITIVE",
            "NEUTRAL",
            "NEGATIVE"
          ]
        },
        "variant_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "product_title": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "id",
        "feedback",
        "rating",
        "deleted_at",
        "created_at",
        "updated_at",
        "store_id",
        "metadata",
        "message",
        "reply",
        "is_automatic",
        "product_id",
        "order_id",
        "sentiment",
        "variant_id",
        "product_title"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "feedback": "POSITIVE",
    "rating": 5,
    "deleted_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "metadata": {},
    "message": "The download arrived immediately and the setup instructions were clear.",
    "reply": "Please contact support if you need help with your download.",
    "is_automatic": true,
    "product_id": 1,
    "order_id": 1,
    "sentiment": "POSITIVE",
    "variant_id": null,
    "product_title": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve specific feedback (/docs/api/feedback/retrieve-specific-feedback)

Retrieve a customer's feedback by its ID.

## GET /v2/feedback/{feedback}

Retrieve specific feedback

Retrieve a customer's feedback by its ID. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.feedback.v2GetFeedback({
  "feedback": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.feedback.v2_get_feedback(feedback=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->feedback()->v2GetFeedback(feedback: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Feedback().V2GetFeedback(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Feedback.V2GetFeedbackAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.feedback.v2GetFeedback(feedback = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.feedback.v2_get_feedback(feedback: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::feedback::V2GetFeedbackParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2GetFeedbackParams::default();
    let result = client.feedback().v_2_get_feedback("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Feedback.v2_get_feedback(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp feedback v-2-get-feedback 1

```

- Method: `GET`

- Path: `/v2/feedback/{feedback}`

- Full URL: `https://sell.app/api/v2/feedback/{feedback}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `customers:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_FEEDBACK_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/feedback/${SELLAPP_FEEDBACK_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `feedback` (`integer`, required): The feedback path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "feedback": {
          "type": "string"
        },
        "rating": {
          "type": [
            "integer",
            "null"
          ]
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "metadata": {
          "type": "object",
          "additionalProperties": true
        },
        "message": {
          "type": [
            "string",
            "null"
          ]
        },
        "reply": {
          "type": [
            "string",
            "null"
          ]
        },
        "is_automatic": {
          "type": "boolean"
        },
        "product_id": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Product associated with the feedback, when available."
        },
        "order_id": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Purchase associated with the feedback, when available."
        },
        "sentiment": {
          "type": "string",
          "enum": [
            "POSITIVE",
            "NEUTRAL",
            "NEGATIVE"
          ]
        },
        "variant_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "product_title": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "id",
        "feedback",
        "rating",
        "deleted_at",
        "created_at",
        "updated_at",
        "store_id",
        "metadata",
        "message",
        "reply",
        "is_automatic",
        "product_id",
        "order_id",
        "sentiment",
        "variant_id",
        "product_title"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "feedback": "POSITIVE",
    "rating": 5,
    "deleted_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "metadata": {},
    "message": "The download arrived immediately and the setup instructions were clear.",
    "reply": "Thank you for your feedback.",
    "is_automatic": true,
    "product_id": 1,
    "order_id": 1,
    "sentiment": "POSITIVE",
    "variant_id": null,
    "product_title": null
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Search feedback (/docs/api/feedback/search-feedback)

Search feedback with filters, search terms, includes, and sort instructions in a JSON request body.

## POST /v2/feedback/search

Search feedback

Search feedback using JSON body filters, search terms, includes, and sort instructions. This v2 route is store-scoped. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.feedback.v2SearchFeedback({
  "filters": [{"field": "id", "operator": "=", "value": 1}],
  "sort": [{"field": "created_at", "direction": "desc"}]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.feedback.v2_search_feedback(
    filters=[{"field": "id", "operator": "=", "value": 1}],
    sort=[{"field": "created_at", "direction": "desc"}]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->feedback()->v2SearchFeedback(
    filters: [['field' => 'id', 'operator' => '=', 'value' => 1]],
    sort: [['field' => 'created_at', 'direction' => 'desc']],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.FeedbackV2SearchFeedbackParams{}
    if err := json.Unmarshal([]byte("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}"), params); err != nil { panic(err) }
    page := client.Feedback().V2SearchFeedback(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Feedback.V2SearchFeedbackAsync(new FeedbackV2SearchFeedbackOptions
    {
        Filters = JsonConvert.DeserializeObject<List<V2SearchFeedbackRequestApplicationJsonPropertyFiltersItem>>("[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}]")!,
        Sort = JsonConvert.DeserializeObject<List<V2SearchFeedbackRequestApplicationJsonPropertySortItem>>("[{\"field\":\"created_at\",\"direction\":\"desc\"}]")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.feedback.v2SearchFeedback(filters = listOf(ObjectMapperFactory.read("{\"field\":\"id\",\"operator\":\"=\",\"value\":1}", app.sell.sellapp.models.V2SearchFeedbackRequestApplicationJsonPropertyFiltersItem::class.java)), sort = listOf(ObjectMapperFactory.read("{\"field\":\"created_at\",\"direction\":\"desc\"}", app.sell.sellapp.models.V2SearchFeedbackRequestApplicationJsonPropertySortItem::class.java)))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.feedback.v2_search_feedback(
  filters: [{ field: "id", operator: "=", value: 1 }],
  sort: [{ field: "created_at", direction: "desc" }]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::feedback::V2SearchFeedbackParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = V2SearchFeedbackParams::new(serde_json::from_str("{\"filters\":[{\"field\":\"id\",\"operator\":\"=\",\"value\":1}],\"sort\":[{\"field\":\"created_at\",\"direction\":\"desc\"}]}")?);
    let result = client.feedback().v_2_search_feedback(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Feedback.v2_search_feedback(client, %{"filters" => [%{"field" => "id", "operator" => "=", "value" => 1}], "sort" => [%{"field" => "created_at", "direction" => "desc"}]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp feedback v-2-search-feedback --body '{"filters":[{"field":"id","operator":"=","value":1}],"sort":[{"field":"created_at","direction":"desc"}]}'

```

- Method: `POST`

- Path: `/v2/feedback/search`

- Full URL: `https://sell.app/api/v2/feedback/search`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `customers:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/feedback/search" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: No

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "operator": {
            "type": "string",
            "default": "="
          },
          "value": {},
          "type": {
            "type": "string",
            "enum": [
              "and",
              "or"
            ],
            "default": "and"
          },
          "nested": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "anyOf": [
          {
            "required": [
              "field"
            ]
          },
          {
            "required": [
              "nested"
            ]
          }
        ]
      }
    },
    "sort": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "default": "asc"
          }
        },
        "required": [
          "field"
        ]
      }
    },
    "search": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "null"
          ]
        },
        "case_sensitive": {
          "type": "boolean"
        }
      }
    },
    "includes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "relation": {
            "type": "string"
          }
        },
        "required": [
          "relation"
        ]
      }
    }
  }
}
```

Example:

```json
{
  "filters": [
    {
      "field": "id",
      "operator": "=",
      "value": 1
    }
  ],
  "sort": [
    {
      "field": "created_at",
      "direction": "desc"
    }
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "feedback": {
            "type": "string"
          },
          "rating": {
            "type": [
              "integer",
              "null"
            ]
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "message": {
            "type": [
              "string",
              "null"
            ]
          },
          "reply": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_automatic": {
            "type": "boolean"
          },
          "product_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Product associated with the feedback, when available."
          },
          "order_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Purchase associated with the feedback, when available."
          },
          "sentiment": {
            "type": "string",
            "enum": [
              "POSITIVE",
              "NEUTRAL",
              "NEGATIVE"
            ]
          },
          "variant_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "product_title": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "feedback",
          "rating",
          "deleted_at",
          "created_at",
          "updated_at",
          "store_id",
          "metadata",
          "message",
          "reply",
          "is_automatic",
          "product_id",
          "order_id",
          "sentiment",
          "variant_id",
          "product_title"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "feedback": "POSITIVE",
      "rating": 5,
      "deleted_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "metadata": {},
      "message": "The download arrived immediately and the setup instructions were clear.",
      "reply": "Thank you for your feedback.",
      "is_automatic": true,
      "product_id": 1,
      "order_id": 1,
      "sentiment": "POSITIVE",
      "variant_id": null,
      "product_title": null
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/feedback/search?page=1",
    "last": "https://sell.app/api/v2/feedback/search?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/feedback/search",
    "per_page": 20,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/feedback/search?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Exports (/docs/api/exports)

Create a report without keeping your request open. Each export has its own UUID
and saved progress, so you can check it later. Exports cover several kinds of
store data and are available at `/v2/exports` independently of any one order.

Reports contain real store data. Keep downloaded files private. SellApp records
who requested an export; the response does not expose that person's identifier.

## Permissions by report type [#permissions-by-report-type]

Send `X-STORE` with your store slug. You need an API key with the listed ability
or an OAuth token with the listed effective scope. In both cases, your account
must have the listed current store permissions.

| `type`                      | API-key ability | OAuth create scope | OAuth list, retrieve, download scope | Store permissions                       |
| --------------------------- | --------------- | ------------------ | ------------------------------------ | --------------------------------------- |
| `sales`, `tax`, `customers` | `invoice`       | `orders:write`     | `orders:read`                        | `invoice`                               |
| `affiliate_payouts`         | `affiliate`     | `payments:write`   | `payments:read`                      | Both `affiliate` and `affiliate:payout` |

The list returns only report types you may access, 50 reports per page.
Retrieving or downloading another store's export returns `404`; lacking access
to its report category returns `403`. Affiliate payout reports describe
commissions and merchant-recorded payments, not transfers made by SellApp.

## Create, check, and download [#create-check-and-download]

Use `csv` or `json` for any supported type. Optional `parameters.from` and
`parameters.to` use `YYYY-MM-DD`. When both are supplied, the range can span at
most 366 calendar days. Tax reports accept `parameters.report_type` as `summary`
or `detailed`. Report generation has finite resource limits; split large reports
into smaller date ranges where supported.

Set the environment variables from [the quickstart](/api/quickstart).
These Bash commands require `jq` and create a real export. Save one
`EXPORT_REQUEST_KEY` for this request; reuse it only for an identical retry.

```bash title="Create a sales export"
EXPORT_REQUEST_KEY="$(openssl rand -hex 16)"
EXPORT_RESPONSE="$(curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/exports" \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE_SLUG}" \
  --header "Idempotency-Key: ${EXPORT_REQUEST_KEY}" \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{"type":"sales","format":"csv","parameters":{"from":"2026-08-01","to":"2026-08-31"}}')"
EXPORT_ID="$(printf '%s' "$EXPORT_RESPONSE" | jq -er '.data.id')"
```

The response includes `meta.poll_after_seconds: 2`. Wait at least that long,
then retrieve the returned ID. Repeat this read while status is `pending` or
`running`; do not create a new export on every poll.

```bash title="Check the export"
EXPORT_RESPONSE="$(curl --fail-with-body \
  --url "${SELLAPP_API_BASE_URL}/v2/exports/${EXPORT_ID}" \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE_SLUG}" \
  --header 'Accept: application/json')"
printf '%s' "$EXPORT_RESPONSE" | jq '.data | {id, status, filename, size, expires_at}'
```

The resource includes `type`, `format`, `parameters`, `status`, `filename`,
`content_type`, byte `size`, and `failure_message`. Timestamps describe creation,
updates, the start of generation, completion, failure, and expiration. Artifact
metadata and lifecycle timestamps can be `null` before the corresponding step.

When status is `completed` and `expires_at` is in the future, use the returned
`download_url`. It is a signed SellApp API URL valid for five minutes. Request it
with your credential and `X-STORE`; it redirects to a separate private storage
URL valid for five minutes. Send your API credential only to SellApp, not to the
storage URL. Do not log either signed URL. Retrieve the export again if the
SellApp download link expires while the artifact is still available.

## Failures and expiration [#failures-and-expiration]

A download attempted before completion returns `409`. An expired artifact
returns `410`, even if its last reported status still says `completed`.
Expired artifacts have no `download_url`. Expiration cleanup may finish later;
that does not extend download access.

Generation is attempted once. If status becomes `failed`, inspect the public
`failure_message`, then create a new export with a new request key when ready.
Retrying the original keyed create request retrieves the original result; it
does not restart failed generation. A missing artifact can return `404`.

## POST /v2/exports

Create an export

Create a persisted asynchronous sales, tax, customer or affiliate payout report. Date ranges may span at most 366 calendar days. Generation uses memory-backed writers; large reports are subject to available capacity. Create a new export after failure. The requesting actor is recorded but is not returned in this response. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply. Sales, tax and customer reports require the invoice credential ability and invoice store permission (orders:read for reads, orders:write for creation with OAuth). Affiliate payout reports require the affiliate credential ability, affiliate and affiliate:payout store permissions (payments:read for reads, payments:write for creation with OAuth). The category selects the applicable alternative. Listing returns only authorized categories.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.exports.createExport({
  "type": "sales",
  "format": "csv",
  "parameters": {"from": "2026-08-01", "to": "2026-08-31"}
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.exports.create_export(
    type="sales",
    format="csv",
    parameters={"from": "2026-08-01", "to": "2026-08-31"}
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->exports()->createExport(
    type: 'sales',
    format: 'csv',
    parameters: ['from' => '2026-08-01', 'to' => '2026-08-31'],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.ExportsCreateParams{}
    if err := json.Unmarshal([]byte("{\"type\":\"sales\",\"format\":\"csv\",\"parameters\":{\"from\":\"2026-08-01\",\"to\":\"2026-08-31\"}}"), params); err != nil { panic(err) }
    result, err := client.Exports().Create(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Exports.CreateAsync(new ExportsCreateOptions
    {
        Type = JsonConvert.DeserializeObject<SdkCreateExportRequestApplicationJsonType>("\"sales\"")!,
        Format = JsonConvert.DeserializeObject<SdkCreateExportRequestApplicationJsonFormat>("\"csv\"")!,
        Parameters = JsonConvert.DeserializeObject<CreateExportRequestApplicationJsonPropertyParameters>("{\"from\":\"2026-08-01\",\"to\":\"2026-08-31\"}")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.exports.create(type = app.sell.sellapp.types.SdkCreateExportRequestApplicationJsonType("sales"), format = app.sell.sellapp.types.SdkCreateExportRequestApplicationJsonFormat("csv"), parameters = ObjectMapperFactory.read("{\"from\":\"2026-08-01\",\"to\":\"2026-08-31\"}", app.sell.sellapp.models.CreateExportRequestApplicationJsonPropertyParameters::class.java))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.exports.create_export(
  type: "sales",
  format: "csv",
  parameters: { from: "2026-08-01", to: "2026-08-31" }
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::exports::CreateExportParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateExportParams::new(serde_json::from_str("{\"type\":\"sales\",\"format\":\"csv\",\"parameters\":{\"from\":\"2026-08-01\",\"to\":\"2026-08-31\"}}")?);
    let result = client.exports().create_export(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Exports.create_export(client, %{"type" => "sales", "format" => "csv", "parameters" => %{"from" => "2026-08-01", "to" => "2026-08-31"}})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp exports create-export --body '{"type":"sales","format":"csv","parameters":{"from":"2026-08-01","to":"2026-08-31"}}' --yes

```

- Method: `POST`

- Path: `/v2/exports`

- Full URL: `https://sell.app/api/v2/exports`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.) OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/exports" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "type": "sales",
  "format": "csv",
  "parameters": {
    "from": "2026-08-01",
    "to": "2026-08-31"
  }
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.
- `Idempotency-Key` (`string`, optional): Reuse this key only for an identical retry. A replay returns Idempotent-Replayed: true.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "format"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "sales",
        "tax",
        "customers",
        "affiliate_payouts"
      ]
    },
    "format": {
      "type": "string",
      "enum": [
        "csv",
        "json"
      ]
    },
    "parameters": {
      "type": "object",
      "properties": {
        "from": {
          "type": [
            "string",
            "null"
          ],
          "format": "date"
        },
        "to": {
          "type": [
            "string",
            "null"
          ],
          "format": "date"
        },
        "report_type": {
          "type": "string",
          "enum": [
            "summary",
            "detailed"
          ]
        }
      }
    }
  }
}
```

Example:

```json
{
  "type": "sales",
  "format": "csv",
  "parameters": {
    "from": "2026-08-01",
    "to": "2026-08-31"
  }
}
```

## Responses

### 201

Created.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Idempotent-Replayed` (`boolean`, optional): True for a stored identical retry response.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data",
    "meta"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "type",
        "format",
        "status",
        "parameters",
        "filename",
        "content_type",
        "size",
        "failure_message",
        "started_at",
        "completed_at",
        "failed_at",
        "expires_at",
        "created_at",
        "updated_at"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "type": {
          "type": "string",
          "enum": [
            "sales",
            "tax",
            "customers",
            "affiliate_payouts"
          ]
        },
        "format": {
          "type": "string",
          "enum": [
            "csv",
            "json"
          ]
        },
        "status": {
          "type": "string",
          "enum": [
            "pending",
            "running",
            "completed",
            "failed",
            "expired"
          ]
        },
        "parameters": {
          "type": "object",
          "properties": {
            "from": {
              "type": [
                "string",
                "null"
              ],
              "format": "date"
            },
            "to": {
              "type": [
                "string",
                "null"
              ],
              "format": "date"
            },
            "report_type": {
              "type": "string",
              "enum": [
                "summary",
                "detailed"
              ]
            }
          }
        },
        "download_url": {
          "type": "string",
          "format": "uri",
          "description": "Present only for a completed export with an unexpired artifact. This signed URL requires authentication and store authorization, and expires after five minutes."
        },
        "filename": {
          "type": [
            "string",
            "null"
          ]
        },
        "content_type": {
          "type": [
            "string",
            "null"
          ]
        },
        "size": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "failure_message": {
          "type": [
            "string",
            "null"
          ]
        },
        "started_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "completed_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "failed_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "poll_after_seconds"
      ],
      "properties": {
        "poll_after_seconds": {
          "type": "integer",
          "minimum": 1
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
```

Example:

```json
{
  "data": {
    "id": "01992a65-e064-71ba-b38f-902b7966a6be",
    "type": "sales",
    "format": "csv",
    "status": "pending",
    "parameters": {
      "from": "2026-08-01",
      "to": "2026-08-31"
    },
    "filename": null,
    "content_type": null,
    "size": null,
    "failure_message": null,
    "started_at": null,
    "completed_at": null,
    "failed_at": null,
    "expires_at": null,
    "created_at": "2026-09-04T09:12:00Z",
    "updated_at": "2026-09-04T09:12:03Z"
  },
  "meta": {
    "poll_after_seconds": 2
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/exports

List exports

List permitted exports, 50 per page. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply. Sales, tax and customer reports require the invoice credential ability and invoice store permission (orders:read for reads, orders:write for creation with OAuth). Affiliate payout reports require the affiliate credential ability, affiliate and affiliate:payout store permissions (payments:read for reads, payments:write for creation with OAuth). The category selects the applicable alternative. Listing returns only authorized categories.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.exports.listExports();
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.exports.list_exports()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->exports()->listExports();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    page := client.Exports().List(context.Background())
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Exports.ListAsync();
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.exports.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.exports.list_exports
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::exports::ListExportsParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListExportsParams::default();
    let result = client.exports().list_exports(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Exports.list_exports(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp exports list-exports

```

- Method: `GET`

- Path: `/v2/exports`

- Full URL: `https://sell.app/api/v2/exports`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.) OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/exports" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data",
    "links",
    "meta"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "type",
          "format",
          "status",
          "parameters",
          "filename",
          "content_type",
          "size",
          "failure_message",
          "started_at",
          "completed_at",
          "failed_at",
          "expires_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "sales",
              "tax",
              "customers",
              "affiliate_payouts"
            ]
          },
          "format": {
            "type": "string",
            "enum": [
              "csv",
              "json"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "completed",
              "failed",
              "expired"
            ]
          },
          "parameters": {
            "type": "object",
            "properties": {
              "from": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date"
              },
              "to": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date"
              },
              "report_type": {
                "type": "string",
                "enum": [
                  "summary",
                  "detailed"
                ]
              }
            }
          },
          "download_url": {
            "type": "string",
            "format": "uri",
            "description": "Present only for a completed export with an unexpired artifact. This signed URL requires authentication and store authorization, and expires after five minutes."
          },
          "filename": {
            "type": [
              "string",
              "null"
            ]
          },
          "content_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "size": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "failure_message": {
            "type": [
              "string",
              "null"
            ]
          },
          "started_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "failed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      }
    },
    "links": {
      "type": "object",
      "required": [
        "first",
        "last",
        "prev",
        "next"
      ],
      "properties": {
        "first": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=1"
        },
        "last": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists?page=4"
        },
        "prev": {
          "type": [
            "string",
            "null"
          ],
          "example": null
        },
        "next": {
          "type": [
            "string",
            "null"
          ],
          "example": "https://sell.app/api/v1/blacklists?page=2"
        }
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "current_page",
        "from",
        "last_page",
        "links",
        "path",
        "per_page",
        "to",
        "total"
      ],
      "properties": {
        "current_page": {
          "type": "integer",
          "example": 1
        },
        "from": {
          "type": [
            "integer",
            "null"
          ],
          "example": 1
        },
        "last_page": {
          "type": "integer",
          "example": 4
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "url",
              "label",
              "active"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": "string"
              },
              "active": {
                "type": "boolean"
              }
            }
          }
        },
        "path": {
          "type": "string",
          "example": "https://sell.app/api/v1/blacklists"
        },
        "per_page": {
          "type": "integer",
          "example": 15
        },
        "to": {
          "type": [
            "integer",
            "null"
          ],
          "example": 15
        },
        "total": {
          "type": "integer",
          "example": 57
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": [
    {
      "id": "01992a65-e064-71ba-b38f-902b7966a6be",
      "type": "sales",
      "format": "csv",
      "status": "completed",
      "parameters": {
        "from": "2026-08-01",
        "to": "2026-08-31"
      },
      "download_url": "https://sell.app/api/v2/exports/01992a65-e064-71ba-b38f-902b7966a6be/download?expires=1788513423&signature=2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65",
      "filename": "sales-2026-08-01-to-2026-08-31.csv",
      "content_type": "text/csv",
      "size": 18432,
      "failure_message": null,
      "started_at": "2026-09-04T09:12:01Z",
      "completed_at": "2026-09-04T09:12:03Z",
      "failed_at": null,
      "expires_at": "2026-09-05T09:12:03Z",
      "created_at": "2026-09-04T09:12:00Z",
      "updated_at": "2026-09-04T09:12:03Z"
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/exports?page=1",
    "last": "https://sell.app/api/v2/exports?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/exports",
    "per_page": 50,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/exports?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/exports/{export}

Retrieve an export

Poll until completed, failed, or expired. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply. Sales, tax and customer reports require the invoice credential ability and invoice store permission (orders:read for reads, orders:write for creation with OAuth). Affiliate payout reports require the affiliate credential ability, affiliate and affiliate:payout store permissions (payments:read for reads, payments:write for creation with OAuth). The category selects the applicable alternative. Listing returns only authorized categories.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.exports.getExport({
  "export": "01992a65-e064-71ba-b38f-902b7966a6be"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.exports.get_export(export="01992a65-e064-71ba-b38f-902b7966a6be")
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->exports()->getExport(export: '01992a65-e064-71ba-b38f-902b7966a6be');
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Exports().Get(context.Background(), "01992a65-e064-71ba-b38f-902b7966a6be")
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Exports.GetAsync("01992a65-e064-71ba-b38f-902b7966a6be");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.exports.get(export = "01992a65-e064-71ba-b38f-902b7966a6be")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.exports.get_export(export: "01992a65-e064-71ba-b38f-902b7966a6be")
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::exports::GetExportParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetExportParams::default();
    let result = client.exports().get_export("01992a65-e064-71ba-b38f-902b7966a6be", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Exports.get_export(client, "01992a65-e064-71ba-b38f-902b7966a6be")
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp exports get-export 01992a65-e064-71ba-b38f-902b7966a6be

```

- Method: `GET`

- Path: `/v2/exports/{export}`

- Full URL: `https://sell.app/api/v2/exports/{export}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.) OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_EXPORT_ID='01992a65-e064-71ba-b38f-902b7966a6be'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/exports/${SELLAPP_EXPORT_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `export` (`string`, format `uuid`, required): The export identifier.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "id",
        "type",
        "format",
        "status",
        "parameters",
        "filename",
        "content_type",
        "size",
        "failure_message",
        "started_at",
        "completed_at",
        "failed_at",
        "expires_at",
        "created_at",
        "updated_at"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "type": {
          "type": "string",
          "enum": [
            "sales",
            "tax",
            "customers",
            "affiliate_payouts"
          ]
        },
        "format": {
          "type": "string",
          "enum": [
            "csv",
            "json"
          ]
        },
        "status": {
          "type": "string",
          "enum": [
            "pending",
            "running",
            "completed",
            "failed",
            "expired"
          ]
        },
        "parameters": {
          "type": "object",
          "properties": {
            "from": {
              "type": [
                "string",
                "null"
              ],
              "format": "date"
            },
            "to": {
              "type": [
                "string",
                "null"
              ],
              "format": "date"
            },
            "report_type": {
              "type": "string",
              "enum": [
                "summary",
                "detailed"
              ]
            }
          }
        },
        "download_url": {
          "type": "string",
          "format": "uri",
          "description": "Present only for a completed export with an unexpired artifact. This signed URL requires authentication and store authorization, and expires after five minutes."
        },
        "filename": {
          "type": [
            "string",
            "null"
          ]
        },
        "content_type": {
          "type": [
            "string",
            "null"
          ]
        },
        "size": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "failure_message": {
          "type": [
            "string",
            "null"
          ]
        },
        "started_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "completed_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "failed_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "expires_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      }
    }
  }
}
```

Example:

```json
{
  "data": {
    "id": "01992a65-e064-71ba-b38f-902b7966a6be",
    "type": "sales",
    "format": "csv",
    "status": "completed",
    "parameters": {
      "from": "2026-08-01",
      "to": "2026-08-31"
    },
    "download_url": "https://sell.app/api/v2/exports/01992a65-e064-71ba-b38f-902b7966a6be/download?expires=1788513423&signature=2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65",
    "filename": "sales-2026-08-01-to-2026-08-31.csv",
    "content_type": "text/csv",
    "size": 18432,
    "failure_message": null,
    "started_at": "2026-09-04T09:12:01Z",
    "completed_at": "2026-09-04T09:12:03Z",
    "failed_at": null,
    "expires_at": "2026-09-05T09:12:03Z",
    "created_at": "2026-09-04T09:12:00Z",
    "updated_at": "2026-09-04T09:12:03Z"
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

---

## GET /v2/exports/{export}/download

Download an export

Validate the five-minute signed API URL, then redirect to a short-lived private object-storage URL. The API does not stream the file. Pending or running exports return 409; expired exports return 410. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply. Sales, tax and customer reports require the invoice credential ability and invoice store permission (orders:read for reads, orders:write for creation with OAuth). Affiliate payout reports require the affiliate credential ability, affiliate and affiliate:payout store permissions (payments:read for reads, payments:write for creation with OAuth). The category selects the applicable alternative. Listing returns only authorized categories.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.exports.downloadExport({
  "export": "01992a65-e064-71ba-b38f-902b7966a6be",
  "expires": 1788513423,
  "signature": "2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65"
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.exports.download_export(
    export="01992a65-e064-71ba-b38f-902b7966a6be",
    expires=1788513423,
    signature="2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65"
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->exports()->downloadExport(
    export: '01992a65-e064-71ba-b38f-902b7966a6be',
    expires: 1788513423,
    signature: '2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65',
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.ExportsDownloadParams{}
    if err := json.Unmarshal([]byte("1788513423"), &params.Expires); err != nil { panic(err) }
    if err := json.Unmarshal([]byte("\"2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65\""), &params.Signature); err != nil { panic(err) }
    if err := client.Exports().Download(context.Background(), "01992a65-e064-71ba-b38f-902b7966a6be", params); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.Exports.DownloadAsync(
    "01992a65-e064-71ba-b38f-902b7966a6be",
    new ExportsDownloadOptions
    {
        Expires = 1788513423,
        Signature = "2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65",
    }
);
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.exports.download(export = "01992a65-e064-71ba-b38f-902b7966a6be", expires = 1788513423L, signature = "2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.exports.download_export(
  export: "01992a65-e064-71ba-b38f-902b7966a6be",
  expires: 1788513423,
  signature: "2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65"
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::exports::DownloadExportParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = DownloadExportParams::new(serde_json::from_str("1788513423")?, "2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65");
    let result = client.exports().download_export("01992a65-e064-71ba-b38f-902b7966a6be", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Exports.download_export(client, "01992a65-e064-71ba-b38f-902b7966a6be", %{"expires" => 1788513423, "signature" => "2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65"})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp exports download-export 01992a65-e064-71ba-b38f-902b7966a6be --expires 1788513423 --signature 2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65

```

- Method: `GET`

- Path: `/v2/exports/{export}/download`

- Full URL: `https://sell.app/api/v2/exports/{export}/download`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `orders:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.) OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `payments:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_EXPORT_ID='01992a65-e064-71ba-b38f-902b7966a6be'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/exports/${SELLAPP_EXPORT_ID}/download?expires=1788513423&signature=2c91df645a086ec399153a932b741f809d2b85c69740eaf3612384ebfb913a65" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `export` (`string`, format `uuid`, required): The export identifier.

## Query Parameters
- `expires` (`integer`, required): Expiry timestamp from the generated download URL.
- `signature` (`string`, required): Copy the signature from the response-supplied download_url. The example is illustrative and cannot authorize a download.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 302

Redirect to a five-minute private object-storage download URL.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Location` (`string`, format `uri`, optional): Short-lived private object-storage URL.
- `Cache-Control` (`string`, optional): Prevents the signed redirect from being cached.

No structured response body documented.

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 409

The request conflicts with the resource's current state.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "conflict_error",
  "code": "conflict",
  "message": "The resource state changed before this request.",
  "status": 409,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#conflict"
}
```

### 410

The signed cursor or temporary resource has expired.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "cursor_expired",
  "message": "This cursor has expired. Start again without a cursor.",
  "status": 410,
  "param": "cursor",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#cursor-expired"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Add products to group (/docs/api/groups/add-products-to-group)

Add existing products to a group.

## POST /v2/groups/{group}/products/attach

Add products to group

Add existing products to a group. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.groupsProducts.add({
  "group": 1,
  "resources": [1]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.groups_products.add(
    group=1,
    resources=[1]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->groupsProducts()->add(
    group: 1,
    resources: [1],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.GroupsProductsAddParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[1]}"), params); err != nil { panic(err) }
    result, err := client.GroupsProducts().Add(context.Background(), 1, params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.GroupsProducts.AddAsync(
    "1",
    new GroupsProductsAddOptions
    {
        Resources = JsonConvert.DeserializeObject<List<long>>("[1]")!,
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.groupsProducts.add(group = "1", resources = listOf(1L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.groups_products.add(
  group: 1,
  resources: [1]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::groups_products::AddParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = AddParams::new(serde_json::from_str("{\"resources\":[1]}")?);
    let result = client.groups_products().add("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.GroupsProducts.add(client, 1, %{"resources" => [1]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp groups products add 1 --body '{"resources":[1]}' --yes

```

- Method: `POST`

- Path: `/v2/groups/{group}/products/attach`

- Full URL: `https://sell.app/api/v2/groups/{group}/products/attach`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_GROUP_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/groups/${SELLAPP_GROUP_ID}/products/attach" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    1
  ]
}'
```

## Path Parameters
- `group` (`integer`, required): The group path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "integer"
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    1
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "attached": {
      "type": "array",
      "items": {
        "type": "integer"
      }
    }
  },
  "required": [
    "attached"
  ]
}
```

Example:

```json
{
  "attached": [
    1
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Create a group (/docs/api/groups/create-a-group)

Create a group for related products.

## POST /v2/groups

Create a group

Create a group for related products. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.groups.create({
  "title": "Design kit",
  "unlisted": true
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.groups.create(
    title="Design kit",
    unlisted=True
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->groups()->create(
    title: 'Design kit',
    unlisted: true,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.GroupsCreateParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Design kit\",\"unlisted\":true}"), params); err != nil { panic(err) }
    result, err := client.Groups().Create(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Groups.CreateAsync(new GroupsCreateOptions
    {
        Title = "Design kit",
        Unlisted = true,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.groups.create(title = "Design kit", unlisted = true)
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.groups.create(
  title: "Design kit",
  unlisted: true
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::groups::CreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateParams::new(serde_json::from_str("{\"title\":\"Design kit\",\"unlisted\":true}")?);
    let result = client.groups().create(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Groups.create(client, %{"title" => "Design kit", "unlisted" => true})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp groups create --title 'Design kit' --unlisted true

```

### Minimal valid request (minimal)

Request content type: `application/json`

```json
{
  "title": "Design kit",
  "unlisted": true
}
```

#### Official node

```node
import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.groups.create({
  "title": "Design kit",
  "unlisted": true
});
console.log(result);
```

#### Official python

```python
import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.groups.create(
    title="Design kit",
    unlisted=True
)
print(result)
```

#### Official php

```php
<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->groups()->create(
    title: 'Design kit',
    unlisted: true,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
```

#### Official go

```go
package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.GroupsCreateParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Design kit\",\"unlisted\":true}"), params); err != nil { panic(err) }
    result, err := client.Groups().Create(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}
```

#### Official dotnet

```dotnet
using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Groups.CreateAsync(new GroupsCreateOptions
    {
        Title = "Design kit",
        Unlisted = true,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));
```

#### Official kotlin

```kotlin
import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.groups.create(title = "Design kit", unlisted = true)
    println(result)
}
```

#### Official ruby

```ruby
require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.groups.create(
  title: "Design kit",
  unlisted: true
)
puts result.inspect
```

#### Official rust

```rust
use sellapp::Client;
use sellapp::resources::groups::CreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateParams::new(serde_json::from_str("{\"title\":\"Design kit\",\"unlisted\":true}")?);
    let result = client.groups().create(params).await?;
    println!("{result:?}");
    Ok(())
}
```

#### Official elixir

```elixir
client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Groups.create(client, %{"title" => "Design kit", "unlisted" => true})
IO.inspect(result)
```

#### Official cli

```bash
sellapp groups create --body '{"title":"Design kit","unlisted":true}'
```

### With optional fields (realistic)

Request content type: `application/json`

```json
{
  "title": "Design kit",
  "unlisted": true,
  "order": 1
}
```

#### Official node

```node
import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.groups.create({
  "title": "Design kit",
  "unlisted": true,
  "order": 1
});
console.log(result);
```

#### Official python

```python
import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.groups.create(
    title="Design kit",
    unlisted=True,
    order=1
)
print(result)
```

#### Official php

```php
<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->groups()->create(
    title: 'Design kit',
    unlisted: true,
    order: 1,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
```

#### Official go

```go
package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.GroupsCreateParams{}
    if err := json.Unmarshal([]byte("{\"title\":\"Design kit\",\"unlisted\":true,\"order\":1}"), params); err != nil { panic(err) }
    result, err := client.Groups().Create(context.Background(), params)
    if err != nil { panic(err) }
    fmt.Println(result)
}
```

#### Official dotnet

```dotnet
using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Groups.CreateAsync(new GroupsCreateOptions
    {
        Title = "Design kit",
        Unlisted = true,
        Order = JsonConvert.DeserializeObject<long?>("1")!,
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));
```

#### Official kotlin

```kotlin
import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.groups.create(title = "Design kit", unlisted = true, order = 1L)
    println(result)
}
```

#### Official ruby

```ruby
require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.groups.create(
  title: "Design kit",
  unlisted: true,
  order: 1
)
puts result.inspect
```

#### Official rust

```rust
use sellapp::Client;
use sellapp::resources::groups::CreateParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = CreateParams::new(serde_json::from_str("{\"title\":\"Design kit\",\"unlisted\":true,\"order\":1}")?);
    let result = client.groups().create(params).await?;
    println!("{result:?}");
    Ok(())
}
```

#### Official elixir

```elixir
client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Groups.create(client, %{"title" => "Design kit", "unlisted" => true, "order" => 1})
IO.inspect(result)
```

#### Official cli

```bash
sellapp groups create --body '{"title":"Design kit","unlisted":true,"order":1}'
```

- Method: `POST`

- Path: `/v2/groups`

- Full URL: `https://sell.app/api/v2/groups`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request POST \
  --url "${SELLAPP_API_BASE_URL}/v2/groups" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "title": "Design kit",
  "unlisted": true
}'
```

## Path Parameters
None.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string"
    },
    "unlisted": {
      "type": "boolean"
    },
    "order": {
      "type": [
        "integer",
        "null"
      ]
    }
  },
  "required": [
    "title",
    "unlisted"
  ]
}
```

Example (minimal):

```json
{
  "title": "Design kit",
  "unlisted": true
}
```

Example (realistic):

```json
{
  "title": "Design kit",
  "unlisted": true,
  "order": 1
}
```

### Content Type: `multipart/form-data`

Schema:

```json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string"
    },
    "unlisted": {
      "type": "boolean"
    },
    "order": {
      "type": [
        "integer",
        "null"
      ]
    },
    "image": {
      "type": "string",
      "format": "binary"
    }
  },
  "required": [
    "title",
    "unlisted"
  ]
}
```

Example:

```json
{
  "title": "Design kit",
  "unlisted": true,
  "order": 1
}
```

## Responses

### 201

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "order": {
          "type": "integer"
        },
        "image": {
          "anyOf": [
            {
              "type": "object",
              "description": "The stored group image, or null when the group has none.",
              "properties": {
                "path": {
                  "type": "string"
                },
                "metadata": {
                  "type": "object",
                  "properties": {
                    "size": {
                      "type": "integer"
                    },
                    "filename": {
                      "type": "string"
                    },
                    "extension": {
                      "type": "string"
                    },
                    "mime_type": {
                      "type": "string"
                    }
                  }
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "unlisted": {
          "type": "boolean"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "section_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "section_order": {
          "type": [
            "integer",
            "null"
          ]
        },
        "products_linked": {
          "type": "integer"
        },
        "products": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "id",
        "title",
        "order",
        "image",
        "unlisted",
        "created_at",
        "updated_at",
        "store_id",
        "section_id",
        "section_order",
        "products_linked",
        "products"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "title": "Design kit",
    "order": 1,
    "image": null,
    "unlisted": true,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2026-08-30T12:00:01.000000Z",
    "store_id": 1,
    "section_id": null,
    "section_order": null,
    "products_linked": 0,
    "products": []
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Delete a group (/docs/api/groups/delete-a-group)

Deletes a group.

<Warn>
  This will permanently delete the group and its details.
</Warn>

## DELETE /v2/groups/{group}

Delete a group

Deletes a group. This will permanently delete the group and its details. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.groups.delete({
  "group": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.groups.delete(group=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->groups()->delete(group: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    if err := client.Groups().Delete(context.Background(), 1); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.Groups.DeleteAsync("1");
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.groups.delete(group = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.groups.delete(group: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::groups::DeleteParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = DeleteParams::default();
    let result = client.groups().delete("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Groups.delete(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp groups delete 1 --yes

```

- Method: `DELETE`

- Path: `/v2/groups/{group}`

- Full URL: `https://sell.app/api/v2/groups/{group}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_GROUP_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v2/groups/${SELLAPP_GROUP_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `group` (`integer`, required): The group path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "order": {
          "type": "integer"
        },
        "image": {
          "anyOf": [
            {
              "type": "object",
              "description": "The stored group image, or null when the group has none.",
              "properties": {
                "path": {
                  "type": "string"
                },
                "metadata": {
                  "type": "object",
                  "properties": {
                    "size": {
                      "type": "integer"
                    },
                    "filename": {
                      "type": "string"
                    },
                    "extension": {
                      "type": "string"
                    },
                    "mime_type": {
                      "type": "string"
                    }
                  }
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "unlisted": {
          "type": "boolean"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "section_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "section_order": {
          "type": [
            "integer",
            "null"
          ]
        },
        "products_linked": {
          "type": "integer"
        },
        "products": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "description"
            ]
          }
        }
      },
      "required": [
        "id",
        "title",
        "order",
        "image",
        "unlisted",
        "created_at",
        "updated_at",
        "store_id",
        "section_id",
        "section_order",
        "products_linked",
        "products"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "title": "Project Planning Toolkit",
    "order": 1,
    "image": null,
    "unlisted": false,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "section_id": null,
    "section_order": null,
    "products_linked": 1,
    "products": [
      {
        "id": "1",
        "title": "Project Planning Guide",
        "description": "Includes practical examples and a downloadable checklist."
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Overview (/docs/api/groups)



Groups help customers browse related products together. Add products to a group,
remove them from it, or search its contents without recreating the products.
Both the group and its products must belong to the selected store.

Create and edit operations require the documented listing permissions. Treat
deletion as a destructive catalog change. If the response is lost, check whether
the group still exists before trying again. Each endpoint below shows the fields
it accepts and returns.

## Endpoints [#endpoints]

* [List groups](/api/groups/list-all-groups)
* [Search groups](/api/groups/search-groups)
* [Create a group](/api/groups/create-a-group)
* [Retrieve a group](/api/groups/retrieve-a-group)
* [Update a group](/api/groups/update-a-group)
* [Delete a group](/api/groups/delete-a-group)
* [Add products](/api/groups/add-products-to-group)
* [Remove products](/api/groups/remove-products-from-group)
* [List group products](/api/groups/list-all-products-within-group)
* [Search group products](/api/groups/search-products-within-group)
* [Retrieve a group product](/api/groups/list-specific-product-within-group)


# List all groups (/docs/api/groups/list-all-groups)

List your store's groups, 15 per page by default.

## GET /v2/groups

List all groups

List your store's groups, 15 per page by default. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.groups.list({

});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.groups.list()
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->groups()->list();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.GroupsListParams{}
    page := client.Groups().List(context.Background(), params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Groups.ListAsync(new GroupsListOptions
    {
    });
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.groups.list()
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.groups.list
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::groups::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.groups().list(params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Groups.list(client, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp groups list

```

- Method: `GET`

- Path: `/v2/groups`

- Full URL: `https://sell.app/api/v2/groups`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/groups" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
None.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "order": {
            "type": "integer"
          },
          "image": {
            "anyOf": [
              {
                "type": "object",
                "description": "The stored group image, or null when the group has none.",
                "properties": {
                  "path": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object",
                    "properties": {
                      "size": {
                        "type": "integer"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "extension": {
                        "type": "string"
                      },
                      "mime_type": {
                        "type": "string"
                      }
                    }
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "unlisted": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "section_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "section_order": {
            "type": [
              "integer",
              "null"
            ]
          },
          "products_linked": {
            "type": "integer"
          },
          "products": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "title": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "title",
                "description"
              ]
            }
          }
        },
        "required": [
          "id",
          "title",
          "order",
          "image",
          "unlisted",
          "created_at",
          "updated_at",
          "store_id",
          "section_id",
          "section_order",
          "products_linked",
          "products"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "title": "Project Planning Toolkit",
      "order": 1,
      "image": null,
      "unlisted": false,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "section_id": null,
      "section_order": null,
      "products_linked": 1,
      "products": [
        {
          "id": "1",
          "title": "Project Planning Guide",
          "description": "Includes practical examples and a downloadable checklist."
        }
      ]
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/groups?page=1",
    "last": "https://sell.app/api/v2/groups?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/groups",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/groups?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# List all products within group (/docs/api/groups/list-all-products-within-group)

List the products in a group, 15 per page by default.

## GET /v2/groups/{group}/products

List all products within group

List the products in a group, 15 per page by default. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.groupsProducts.list({
  "group": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.groups_products.list(group=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->groupsProducts()->list(group: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.GroupsProductsListParams{}
    page := client.GroupsProducts().List(context.Background(), 1, params)
    if page.Next() { fmt.Println(page.Current()) } else if page.Err() == nil { fmt.Println("No results.") }
    if err := page.Err(); err != nil { panic(err) }
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.GroupsProducts.ListAsync(
    "1",
    new GroupsProductsListOptions
    {
    }
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.groupsProducts.list(group = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.groups_products.list(group: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::groups_products::ListParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = ListParams::default();
    let result = client.groups_products().list("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.GroupsProducts.list(client, 1, %{})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp groups products list 1

```

- Method: `GET`

- Path: `/v2/groups/{group}/products`

- Full URL: `https://sell.app/api/v2/groups/{group}/products`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_GROUP_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/groups/${SELLAPP_GROUP_ID}/products" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `group` (`integer`, required): The group path parameter.

## Query Parameters
- `limit` (`integer`, optional): Number of items to return per page.
- `page` (`integer`, optional): Page number to return.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "images": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "metadata": {
                  "type": "object",
                  "properties": {
                    "size": {
                      "type": "integer"
                    },
                    "filename": {
                      "type": "string"
                    },
                    "extension": {
                      "type": "string"
                    },
                    "mime_type": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "size",
                    "filename",
                    "extension",
                    "mime_type"
                  ]
                }
              },
              "required": [
                "path",
                "metadata"
              ]
            }
          },
          "order": {
            "type": [
              "integer",
              "null"
            ]
          },
          "visibility": {
            "type": "string"
          },
          "delivery_text": {
            "type": "string"
          },
          "additional_information": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "other_settings": {
            "type": "object",
            "properties": {
              "faq": {
                "type": "array",
                "items": {
                  "type": "object",
                  "description": "One question and answer displayed on a product page.",
                  "properties": {
                    "question": {
                      "type": "string",
                      "description": "The question a customer is likely to ask."
                    },
                    "answer": {
                      "type": "string",
                      "description": "The answer shown with this question on the product page."
                    }
                  },
                  "required": [
                    "answer",
                    "question"
                  ]
                }
              },
              "video_url": {
                "type": "string"
              },
              "redirect_url": {
                "type": "string"
              },
              "product_title": {
                "type": "string"
              },
              "product_description": {
                "type": "string"
              }
            },
            "required": [
              "faq",
              "video_url",
              "redirect_url",
              "product_title",
              "product_description"
            ]
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "store_id": {
            "type": "integer"
          },
          "section_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "section_order": {
            "type": [
              "integer",
              "null"
            ]
          },
          "is_discoverable": {
            "type": "boolean"
          },
          "pivot": {
            "type": "object",
            "properties": {
              "group_id": {
                "type": "integer"
              },
              "listing_id": {
                "type": "integer"
              },
              "order": {
                "type": "integer"
              }
            },
            "required": [
              "group_id",
              "listing_id",
              "order"
            ]
          },
          "default_price": {
            "type": "object",
            "properties": {
              "price": {
                "type": "string"
              },
              "currency": {
                "type": "string"
              }
            },
            "required": [
              "price",
              "currency"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "slug",
          "description",
          "images",
          "order",
          "visibility",
          "delivery_text",
          "additional_information",
          "other_settings",
          "deleted_at",
          "created_at",
          "updated_at",
          "store_id",
          "section_id",
          "section_order",
          "is_discoverable",
          "pivot",
          "default_price"
        ]
      }
    },
    "links": {
      "type": "object",
      "properties": {}
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data",
    "links",
    "meta"
  ]
}
```

Example:

```json
{
  "data": [
    {
      "id": 1,
      "title": "Project Planning Guide",
      "slug": "serial",
      "description": "<p>I am sure of it, Pinky.</p>",
      "images": [],
      "order": 1,
      "visibility": "PUBLIC",
      "delivery_text": "",
      "additional_information": [],
      "warranty": {
        "text": "",
        "time": null,
        "preferredUnit": "MINUTES"
      },
      "other_settings": {
        "faq": [],
        "video_url": "",
        "redirect_url": "",
        "product_title": "",
        "product_description": ""
      },
      "deleted_at": null,
      "created_at": "2022-12-12T12:12:12.000000Z",
      "updated_at": "2022-12-12T12:12:12.000000Z",
      "store_id": 1,
      "category_id": null,
      "section_id": null,
      "section_order": null,
      "is_discoverable": true,
      "pivot": {
        "group_id": 1,
        "listing_id": 1,
        "order": 1
      },
      "default_price": {
        "price": "500",
        "currency": "USD"
      }
    }
  ],
  "links": {
    "first": "https://sell.app/api/v2/groups/1/products?page=1",
    "last": "https://sell.app/api/v2/groups/1/products?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://sell.app/api/v2/groups/1/products",
    "per_page": 15,
    "to": 1,
    "total": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "active": false
      },
      {
        "url": "https://sell.app/api/v2/groups/1/products?page=1",
        "label": "1",
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "active": false
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# List specific product within group (/docs/api/groups/list-specific-product-within-group)

Retrieve one product from a group.

## GET /v2/groups/{group}/products/{product}

List specific product within group

Retrieve one product from a group. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.groupsProducts.get({
  "group": 1,
  "product": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.groups_products.get(
    group=1,
    product=1
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->groupsProducts()->get(
    group: 1,
    product: 1,
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.GroupsProducts().Get(context.Background(), 1, 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.GroupsProducts.GetAsync(
    "1",
    "1"
);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.groupsProducts.get(group = "1", product = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.groups_products.get(
  group: 1,
  product: 1
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::groups_products::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.groups_products().get("1", "1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.GroupsProducts.get(client, 1, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp groups products get --group 1 1

```

- Method: `GET`

- Path: `/v2/groups/{group}/products/{product}`

- Full URL: `https://sell.app/api/v2/groups/{group}/products/{product}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_GROUP_ID='1'
export SELLAPP_PRODUCT_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/groups/${SELLAPP_GROUP_ID}/products/${SELLAPP_PRODUCT_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `group` (`integer`, required): The group path parameter.
- `product` (`integer`, required): The product path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "images": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "path": {
                "type": "string"
              },
              "metadata": {
                "type": "object",
                "properties": {
                  "size": {
                    "type": "integer"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "extension": {
                    "type": "string"
                  },
                  "mime_type": {
                    "type": "string"
                  }
                },
                "required": [
                  "size",
                  "filename",
                  "extension",
                  "mime_type"
                ]
              }
            },
            "required": [
              "path",
              "metadata"
            ]
          }
        },
        "order": {
          "type": [
            "integer",
            "null"
          ]
        },
        "visibility": {
          "type": "string"
        },
        "delivery_text": {
          "type": "string"
        },
        "additional_information": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "other_settings": {
          "type": "object",
          "properties": {
            "faq": {
              "type": "array",
              "items": {
                "type": "object",
                "description": "One question and answer displayed on a product page.",
                "properties": {
                  "question": {
                    "type": "string",
                    "description": "The question a customer is likely to ask."
                  },
                  "answer": {
                    "type": "string",
                    "description": "The answer shown with this question on the product page."
                  }
                },
                "required": [
                  "answer",
                  "question"
                ]
              }
            },
            "video_url": {
              "type": "string"
            },
            "redirect_url": {
              "type": "string"
            },
            "product_title": {
              "type": "string"
            },
            "product_description": {
              "type": "string"
            }
          },
          "required": [
            "faq",
            "video_url",
            "redirect_url",
            "product_title",
            "product_description"
          ]
        },
        "deleted_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "section_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "section_order": {
          "type": [
            "integer",
            "null"
          ]
        },
        "is_discoverable": {
          "type": "boolean"
        },
        "pivot": {
          "type": "object",
          "properties": {
            "group_id": {
              "type": "integer"
            },
            "listing_id": {
              "type": "integer"
            },
            "order": {
              "type": "integer"
            }
          },
          "required": [
            "group_id",
            "listing_id",
            "order"
          ]
        }
      },
      "required": [
        "id",
        "title",
        "slug",
        "description",
        "images",
        "order",
        "visibility",
        "delivery_text",
        "additional_information",
        "other_settings",
        "deleted_at",
        "created_at",
        "updated_at",
        "store_id",
        "section_id",
        "section_order",
        "is_discoverable",
        "pivot"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "title": "Project Planning Guide",
    "slug": "serial",
    "description": "<p>I am sure of it, Pinky.</p>",
    "images": [],
    "order": 1,
    "visibility": "PUBLIC",
    "delivery_text": "",
    "additional_information": [],
    "warranty": {
      "text": "",
      "time": null,
      "preferredUnit": "MINUTES"
    },
    "other_settings": {
      "faq": [],
      "video_url": "",
      "redirect_url": "",
      "product_title": "",
      "product_description": ""
    },
    "deleted_at": null,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "category_id": null,
    "section_id": null,
    "section_order": null,
    "is_discoverable": true,
    "pivot": {
      "group_id": 1,
      "listing_id": 1,
      "order": 1
    }
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Remove products from group (/docs/api/groups/remove-products-from-group)

Remove products from a group without deleting the products.

## DELETE /v2/groups/{group}/products/detach

Remove products from group

Remove products from a group without deleting the products. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.groupsProducts.remove({
  "group": 1,
  "resources": [1]
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.groups_products.remove(
    group=1,
    resources=[1]
)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->groupsProducts()->remove(
    group: 1,
    resources: [1],
);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "encoding/json"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    params := &sellapp.GroupsProductsRemoveParams{}
    if err := json.Unmarshal([]byte("{\"resources\":[1]}"), params); err != nil { panic(err) }
    if err := client.GroupsProducts().Remove(context.Background(), 1, params); err != nil { panic(err) }
    fmt.Println("Request completed.")
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

await client.GroupsProducts.RemoveAsync(
    "1",
    new GroupsProductsRemoveOptions
    {
        Resources = JsonConvert.DeserializeObject<List<long>>("[1]")!,
    }
);
Console.WriteLine("Request completed.");

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.groupsProducts.remove(group = "1", resources = listOf(1L))
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.groups_products.remove(
  group: 1,
  resources: [1]
)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::groups_products::RemoveParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = RemoveParams::new(serde_json::from_str("{\"resources\":[1]}")?);
    let result = client.groups_products().remove("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.GroupsProducts.remove(client, 1, %{"resources" => [1]})
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp groups products remove 1 --body '{"resources":[1]}' --yes

```

- Method: `DELETE`

- Path: `/v2/groups/{group}/products/detach`

- Full URL: `https://sell.app/api/v2/groups/{group}/products/detach`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:write` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_GROUP_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request DELETE \
  --url "${SELLAPP_API_BASE_URL}/v2/groups/${SELLAPP_GROUP_ID}/products/detach" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}" \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "resources": [
    1
  ]
}'
```

## Path Parameters
- `group` (`integer`, required): The group path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body

- Required: Yes

### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "resources": {
      "type": "array",
      "items": {
        "type": "integer"
      }
    }
  },
  "required": [
    "resources"
  ]
}
```

Example:

```json
{
  "resources": [
    1
  ]
}
```

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "detached": {
      "type": "array",
      "items": {
        "type": "integer"
      }
    }
  },
  "required": [
    "detached"
  ]
}
```

Example:

```json
{
  "detached": [
    1
  ]
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    },
    "errors": {
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "example": {
        "product_variant_id": [
          "The selected product variant id is invalid."
        ]
      }
    }
  }
}
```

Example:

```json
{
  "type": "validation_error",
  "code": "validation_failed",
  "message": "The selected product variant id is invalid.",
  "status": 422,
  "param": "product_variant_id",
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#validation-failed",
  "errors": {
    "product_variant_id": [
      "The selected product variant id is invalid."
    ]
  }
}
```

### 429

The API key or unauthenticated client exceeded 60 requests in the current minute.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.
- `Retry-After` (`integer`, optional): Seconds to wait before retrying.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "rate_limit_error",
  "code": "rate_limit_exceeded",
  "message": "Too Many Attempts.",
  "status": 429,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#rate-limit-exceeded"
}
```

### 500

SellApp could not complete the request.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "api_error",
  "code": "api_error",
  "message": "Server Error",
  "status": 500,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#api-error"
}
```

# Retrieve a group (/docs/api/groups/retrieve-a-group)

Retrieve a group by its ID.

## GET /v2/groups/{group}

Retrieve a group

Retrieve a group by its ID. OAuth callers must select an authorized store with X-STORE and hold the scope shown below; current store permissions also apply.

### Official TypeScript reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```typescript

import { SellApp } from 'sellapp';

const client = new SellApp({
  baseUrl: process.env.SELLAPP_API_BASE_URL!,
  apiKey: process.env.SELLAPP_API_KEY!,
  store: process.env.SELLAPP_STORE!,
});

const result = await client.groups.get({
  "group": 1
});
console.log(result);

```

### Official Python reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```python

import os
from sellapp_sdk import SellAppClient

client = SellAppClient(base_url=os.environ["SELLAPP_API_BASE_URL"], api_key=os.environ["SELLAPP_API_KEY"], store=os.environ["SELLAPP_STORE"])

result = client.groups.get(group=1)
print(result)

```

### Official PHP reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```php

<?php
require __DIR__ . '/vendor/autoload.php';

use SellApp\Client;

$client = new Client(
    apiKey: getenv('SELLAPP_API_KEY'),
    baseUrl: getenv('SELLAPP_API_BASE_URL'),
    store: getenv('SELLAPP_STORE'),
);

$result = $client->groups()->get(group: 1);
echo json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;

```

### Official Go reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```go

package main

import (
    "context"
    "fmt"
    "os"
    "github.com/sellapp/sellapp-go"
)

func main() {
    client := sellapp.NewClient(os.Getenv("SELLAPP_API_KEY"), os.Getenv("SELLAPP_STORE"), sellapp.WithBaseURL(os.Getenv("SELLAPP_API_BASE_URL")))
    result, err := client.Groups().Get(context.Background(), 1)
    if err != nil { panic(err) }
    fmt.Println(result)
}

```

### Official .NET reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```csharp

using SellApp;
using Newtonsoft.Json;
using System.Collections.Generic;

var client = new SellAppClient(new SellAppOptions
{
    ApiKey = Environment.GetEnvironmentVariable("SELLAPP_API_KEY"),
    BaseUrl = Environment.GetEnvironmentVariable("SELLAPP_API_BASE_URL"),
    Store = Environment.GetEnvironmentVariable("SELLAPP_STORE"),
});

var result = await client.Groups.GetAsync("1");
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

```

### Official Kotlin reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```kotlin

import app.sell.sellapp.SellApp
import app.sell.sellapp.common.json.ObjectMapperFactory

fun main() {
    val client = SellApp(baseUrl = System.getenv("SELLAPP_API_BASE_URL"), apiKey = System.getenv("SELLAPP_API_KEY"), store = System.getenv("SELLAPP_STORE"))
    val result = client.groups.get(group = "1")
    println(result)
}

```

### Official Ruby reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```ruby

require "sellapp"

client = SellApp::Client.new(base_url: ENV.fetch("SELLAPP_API_BASE_URL"), api_key: ENV.fetch("SELLAPP_API_KEY"), store: ENV.fetch("SELLAPP_STORE"))

result = client.groups.get(group: 1)
puts result.inspect

```

### Official Rust reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```rust

use sellapp::Client;
use sellapp::resources::groups::GetParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(std::env::var("SELLAPP_API_KEY")?, std::env::var("SELLAPP_STORE")?).with_base_url(std::env::var("SELLAPP_API_BASE_URL")?);
    let mut params = GetParams::default();
    let result = client.groups().get("1", params).await?;
    println!("{result:?}");
    Ok(())
}

```

### Official Elixir reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```elixir

client = SellApp.Client.new(
  base_url: System.fetch_env!("SELLAPP_API_BASE_URL"),
  api_key: System.fetch_env!("SELLAPP_API_KEY"),
  store: System.fetch_env!("SELLAPP_STORE")
)

{:ok, result} = SellApp.Groups.get(client, 1)
IO.inspect(result)

```

### Official CLI reference example

Fixed reference example. See [SDK setup](/api/sdks) or [CLI setup](/api/cli). The HTTP playground remains editable.

```bash

sellapp groups get 1

```

- Method: `GET`

- Path: `/v2/groups/{group}`

- Full URL: `https://sell.app/api/v2/groups/{group}`

- Authentication: `Authorization: Bearer <credential>` header required OR `Authorization: Bearer <credential>` header required (official CLI OAuth access token) with scopes `products:read` AND `X-STORE` header required (Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.)

## cURL request

Set credentials and replace example resource IDs with IDs from your store. Requests use real store data; writes are not automatically retried.

```bash
export SELLAPP_API_BASE_URL='https://sell.app/api'
export SELLAPP_GROUP_ID='1'
export SELLAPP_API_KEY='replace-me'
export SELLAPP_STORE='launch-lab'

curl --fail-with-body --request GET \
  --url "${SELLAPP_API_BASE_URL}/v2/groups/${SELLAPP_GROUP_ID}" \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer ${SELLAPP_API_KEY}" \
  --header "X-STORE: ${SELLAPP_STORE}"
```

## Path Parameters
- `group` (`integer`, required): The group path parameter.

## Query Parameters
None.

## Header Parameters
- `Authorization` (`string`, optional): Used by the official CLI: Bearer followed by its OAuth access token. Use an API key for custom integrations where supported.
- `X-STORE` (`string`, optional): Store slug. Required for OAuth access tokens. API keys may omit it to use their current store, or the first accessible store when no current store is selected.

## Request Body
No request body.

## Responses

### 200

Successful response.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string"
        },
        "order": {
          "type": "integer"
        },
        "image": {
          "anyOf": [
            {
              "type": "object",
              "description": "The stored group image, or null when the group has none.",
              "properties": {
                "path": {
                  "type": "string"
                },
                "metadata": {
                  "type": "object",
                  "properties": {
                    "size": {
                      "type": "integer"
                    },
                    "filename": {
                      "type": "string"
                    },
                    "extension": {
                      "type": "string"
                    },
                    "mime_type": {
                      "type": "string"
                    }
                  }
                }
              }
            },
            {
              "type": "null"
            }
          ]
        },
        "unlisted": {
          "type": "boolean"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "store_id": {
          "type": "integer"
        },
        "section_id": {
          "type": [
            "integer",
            "null"
          ]
        },
        "section_order": {
          "type": [
            "integer",
            "null"
          ]
        },
        "products_linked": {
          "type": "integer"
        },
        "products": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title",
              "description"
            ]
          }
        }
      },
      "required": [
        "id",
        "title",
        "order",
        "image",
        "unlisted",
        "created_at",
        "updated_at",
        "store_id",
        "section_id",
        "section_order",
        "products_linked",
        "products"
      ]
    }
  },
  "required": [
    "data"
  ]
}
```

Example:

```json
{
  "data": {
    "id": 1,
    "title": "Project Planning Toolkit",
    "order": 1,
    "image": null,
    "unlisted": false,
    "created_at": "2022-12-12T12:12:12.000000Z",
    "updated_at": "2022-12-12T12:12:12.000000Z",
    "store_id": 1,
    "section_id": null,
    "section_order": null,
    "products_linked": 1,
    "products": [
      {
        "id": "1",
        "title": "Project Planning Guide",
        "description": "Includes practical examples and a downloadable checklist."
      }
    ]
  }
}
```

### 400

Malformed request.

#### Response Headers
None.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "request_id"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer"
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "fallback": {
      "type": "object",
      "required": [
        "transport",
        "url"
      ],
      "properties": {
        "transport": {
          "type": "string",
          "enum": [
            "cursor_polling"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    }
  }
}
```

Example:

```json
{
  "type": "invalid_request_error",
  "code": "bad_request",
  "message": "The request could not be understood.",
  "status": 400,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#bad-request"
}
```

### 401

Authentication failed.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authentication_error",
  "code": "unauthenticated",
  "message": "Unauthenticated.",
  "status": 401,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#unauthenticated"
}
```

### 403

The token lacks the required ability or the actor lacks permission for the selected store.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "authorization_error",
  "code": "forbidden",
  "message": "This action is unauthorized.",
  "status": 403,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#forbidden"
}
```

### 404

The resource does not exist or does not belong to the store selected by X-STORE.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
      "type": "integer",
      "minimum": 400,
      "maximum": 599
    },
    "param": {
      "type": [
        "string",
        "null"
      ]
    },
    "request_id": {
      "type": "string",
      "format": "uuid"
    },
    "docs_url": {
      "type": "string",
      "format": "uri"
    }
  }
}
```

Example:

```json
{
  "type": "not_found_error",
  "code": "resource_not_found",
  "message": "Not Found.",
  "status": 404,
  "param": null,
  "request_id": "01992a65-e064-71ba-b38f-902b7966a6be",
  "docs_url": "https://sell.app/docs/api/errors#resource-not-found"
}
```

### 422

The request payload failed validation.

#### Response Headers
- `X-Request-ID` (`string`, format `uuid`, optional): Server-generated identifier for this request. Log it and include it when contacting SellApp support.
- `X-RateLimit-Limit` (`integer`, optional): Maximum API requests permitted in the current minute.
- `X-RateLimit-Remaining` (`integer`, optional): Requests remaining in the current minute.
- `X-RateLimit-Reset` (`integer`, format `int64`, optional): Unix timestamp when the current rate-limit window resets.

#### Content Type: `application/json`

Schema:

```json
{
  "type": "object",
  "required": [
    "type",
    "code",
    "message",
    "status",
    "param",
    "request_id",
    "docs_url",
    "errors"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "invalid_request_error",
        "authentication_error",
        "authorization_error",
        "not_found_error",
        "conflict_error",
        "validation_error",
        "rate_limit_error",
        "api_error"
      ]
    },
    "code": {
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "status": {
   