# Adding Affiliates (/docs/adding-affiliates)
As a store owner, Users always apply to join your affiliate program via your store's customer portal.
Anyone can apply to join your affiliate program, they do not neccessarily need to have purchased a product from your store before, and they do not need to create a SellApp account or store.
Note that this means you cannot manually add affiliates at this time
***
## Application Flow [#application-flow]
As mentioned above, the application flow starts with a user navigating to your store's customer portal.
There, they will find an "Affiliate Program" option in the sidebar *(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.
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 can no longer reapply. However, you can opt to enable them at any point 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 & 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.
# Introduction (/docs/affiliate-program-introduction)
Create an affiliate program for your store in just a few clicks, and attract affiliates who promote your products in exchange for a commission.
SellApp has built an affiliate system which comes with all the prerequisites to successfully run your affiliate program:
* Flexible configuration options, including the following:
* Auto-approving new affiliates
* Minimum payout amount
* Commission rate
* And more
* 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
***
## The affiliate program explained [#the-affiliate-program-explained]
To get started with the affiliate program, it is important to know how the affiliate program works. Let's start with a 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, the purchase is attributed to them. 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's 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) lets you export pending payouts with all the prerequisite information to pay your affiliates out **(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 is something that 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.
***
## 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 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 on their end.
***
## 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 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
4. **Expire Coupon**: When toggled off, this coupon can be used at any time. When toggled on, you can specify a maximum duration within which a coupon can be used, after which the coupon gets disabled
5. **Apply Storewide**: When toggled on, the coupon can be applied to all products in a store. When toggled off, a dropdown will appear with which you can specify the product(s) that this 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)
This page is dedicated to affiliates who are either part of an affiliate program, or are looking to join an affiliate program
If you're looking to either join an affiliate program of a store, or are already an affiliate, this page is for you.
We will start by explaining how to apply to an affiliate program, and continue with a high-level overview of each 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 this is not your first time applying to an affiliate program, skip the following block of text
***
For first-time affiliates who are not affiliates at other stores, clicking the "Become an Affiliate" button [will redirect you to a form](https://affiliates.sell.app) that you will need to fill in once. Note the following:
* This information cannot be changed further down the line
* The submited information will be visible to all stores you apply to
Once you complete filling in your profile and clicking the "Submit Profile" button, navigate back to the customer portal *(which looks like bob.sell.app/customer-portal/affiliates/join)* and proceed with the below
***
Once you click on the "Apply" button in the /join page, a modal will appear. Here you can see the supported payout methods this store can pay in, and specify your relevant payout details. Additionally, you can write a relevant message to the store explaining your motivations/interest in joining the affiliate program
Once you've clicked "Join" 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. A configurable chart displaying your earnings, both paid and unpaid.
2. Your unique affiliate link, and optionally your unique affiliate coupon code *(if set)*
3. Your 5 most recent referrals generated for the store
4. Your 5 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. Should this be the case for you, this dashboard will display all of the 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 *(if set)* and a description of this coupon's properties.
The coupon can be used to further incentivize potential 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 URL's 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.
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.
# Getting Started (/docs/getting-started-affiliate-program)
There are only two steps involved in launching an affiliate program for your store.
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.
The second step is to fill each of these options in with the values of your choosing, and then saving the changes. Once you've done that, you're good to go!
***
## Affiliate Settings Explained [#affiliate-settings-explained]
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 "Commission Rate Input" from point 6, and instead specify a commission on a product-by-product basis
***
## 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, eveything 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)
Payouts can be viewed at any time [in the Payouts dashboard](https://sell.app/dashboard/affiliates/payouts)
***
## 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 **"Status"** dropdown to **"Due"**
2. Set the **"Payout method"** to **"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"
You will then receive a CSV file that 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, **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)
***
## 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. Accepting pending affiliate requests
2. Disabling and/or re-enabling affiliates
3. 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
* Affiliate 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 "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.
# Managing Referrals (/docs/managing-referrals)
Referrals can be managed at any time [in the Referrals dashboard](https://sell.app/dashboard/affiliates/referrals)
***
## 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
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 a breakdown of 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, and displaying the associated invoice or affiliate.
***
## 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
# Trustpilot (/docs/trustpilot)
With SellApp, you can automatically invite your customers to leave a review on your Trustpilot page.
***
## Setup Guide [#setup-guide]
To start, you'd want to head over 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 settings by clicking here](https://sell.app/dashboard/settings?settings=general) and paste the unique email you copied in step 1 into the "Trustpilot Email" input, then click the "Save" button
That's it! Now, whenever a customer makes a purchase, they will automatically receive an email from Trustpilot inviting them to place a review on your Trustpilot page.
### How it works [#how-it-works]
Whenever a sale is made, your Trustpilot email is BCC'ed into the email that is sent to your customer. This BCC'ed Trustpilot email is then utilized by Trustpilot to automatically send out 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).
# Notifications (/docs/creating-notifications)
You may find yourself wanting to receive a notification when some specific event happens on your SellApp store, such as when an order gets completed, a support ticket is created, or another type of event.
Currently, you can create Discord notifications and email notifications. More notification channels will be added in the future.
***
## 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.
***
## 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.
# Subscriptions (/docs/creating-subscriptions)
With SellApp, you can create products with recurring prices. This means that customers will be charged at a predefined period of time, for example: **daily**, **weekly**, **monthly**
This pricing type is ideal for digital products which require continuous maintenance and effort, with a good example being a SaaS software that is periodically updated and maintaned.
Let's dive into how you can create a product with a recurring subscription.
Currently, you can only create subscriptions after you have [enabled Stripe](/stripe).
***
## Creating a subscription product [#creating-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:
* Specify any kind of subscription duration you'd like. Charge customers every X days, weeks, or months. The highest duration supported is currently 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)
# Discord roling (/docs/discord-roling)
You may find yourself wanting to have your customers join your Discord server and optionally getting a role post-purchase. With SellApp, this is possible by using your own Discord bot.
***
## 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.
***
## Setup and configure bot [#setup-and-configure-bot]
To start setting up the roling functionality, you'll want to create a Discord bot [in the Discord bot dashboard](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 here](https://discord.com/developers/applications/\{botidhere}/oauth2/general), then add the following three redirect URL's on the same page:
* [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. Finally, retrieve your bot token [from here](https://discord.com/developers/applications/\{botidhere}/bot)
Once done, paste the client ID, client secret, and bot token in [your SellApp settings](https://sell.app/dashboard/settings?settings=other) and save.
***
## Add account and server [#add-account-and-server]
Now that your bot credentials have been set and saved, the next step is to add your account and server.
1. Click "Add Account" in [your SellApp settings](https://sell.app/dashboard/settings?settings=other). You will be redirected to Discord, grant the permissions and you will be redirected back to SellApp.
Make sure to edit your Discord server and put the bot's role above the role(s) you are trying to grant. If you don't do so, the bot will not be able to assign the role(s) to the customer's Discord account after a successful purchase.
2. Click the three dots at the end of your account name and click the "Show" option. Click the "+" icon next to "Guilds". You will be redirected to Discord, select the server you want your customers to be added to and optionally roled on.
3. That's all done. You can now see the "Community" option when creating/editing a product and specify which server and role the customer gets, plus an option to make Discord authorization mandatory or not.
You will also be able to update your products in bulk. Select the checkbox at the left hand side on [your products dashboard](https://sell.app/dashboard/listings) -> "Select All" -> "Bulk Update" -> "Discord Data"
Happy selling!
# Payment fee/discount (/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. **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. Enter the discount or fee in the "Discount or fee" input field, then click the "Save" button to the right of the input field.
* To add a discount, enter a positive value. For example, for a 10% discount, enter: 10
* To add a fee, enter a negative value. For example, for a 5% fee, enter: -5
That's all done! The payment method in question will now have a fee/discount applied, which will be visible to the end-user during the checkout process.
Happy selling!
# Embedding products (/docs/embedding-products)
At times, you may want to embed products into a custom-built site of your own, but you don't want to go through the hassle of writing code and/or interacting with our API.
In that event, we offer a seamless embed modal that can be displayed within your own site, and lets visitors make purchases without leaving your website or be redirected to a SellApp product page.
Let's dive into how you can do so.
***
## Generating embed code [#generating-embed-code]
To start generating embed code, you'll want to navigate [to your products dashboard](https://sell.app/dashboard/listings)
1. For the relevant product(s), toggle them on the left hand side next to the product's title
2. Once you've toggled all of the products you'd like to embed, select the "Generate embed code" option in the navigation bar. Here's how that looks
3. A modal will pop up with a HTML file. Here's what you'll want to do:
1. Copy the `` and place it in your site's `
` section
2. Copy the `` and place it right before your site's closing `` section
3. Copy the button(s) and place it in the relevant area where your customer will click
Once done, save your site's code and you'll be good to go. Now, when a visitor clicks on the button that you've pasted, our embed modal will appear and seamlessly guide the visitor through the purchase process.
***
## Embed variables [#embed-variables]
Each embed button can have unique variables set. A list
1. `data-sell-darkmode` Whether the embed is shown in dark mode or light mode. By default, this is set to `false`. Setting the value to `true` will change the embed's design to dark mode.
2. `data-sell-theme` Pass a 6-digit HEX color such as `#FFFFFF` to slightly style the embed.
3. `data-sell-variant` In the event your product has multiple variants and you want to display a specific variant immediately.
4. `data-sell-coupon` Should you wish to automatically apply a coupon code, enter the code here.
5. `data-sell-quantity` To immediately set the purchase quantity, pass a number in this variable.
6. `data-sell-email` Already know the customer's email? Pre-fill it by entering the email here.
7. `data-sell-extra` If the product is priced as "Pay What You Want", you can specify an amount in advance here. Especially useful for wallet top-ups, for example.
8. `data-sell-affiliate` If you want to attribute a sale to an affiliate via the embed, insert the affiliate's identifier in this variable to do so.
9. `data-sell-payment_method` Pre-fill the payment method so the customer doesn't need to select it manually
Looking for a variable that's not in the above list? Send us a message by contacting us via live chat *(found at the bottom right hand corner of this page)*
***
## Checkout example [#checkout-example]
You own a store where customers can purchase credits to use your digital product. You prefer the look of dark mode. Your customers are authenticated, so you are aware of their email address.
One customer, John Doe with email address `johndoe@example.com`, would like to purchase credits for a specific version of your digital product, which happens to be a variant with value `789`.
John intends to top up with 10 credits, so you know the quantity too. Since he is a recurring customer, you would like to give him 10% off with coupon `amazingdiscount`.
With all of the above points in mind, the URL crafted would result in the following: ``
These variables should help streamline your customer's checkout experience and introduce less friction, all in all resulting in a better converting checkout experience.
# Linking a custom domain (/docs/linking-custom-domain)
By default, your SellApp storefront comes with a free subdomain, for example: **admin.sell.app**. However, you can also add a custom domain of your own, for example: **admin.com**
**It's 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.
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** such as **[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.
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, **[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 **[www.example.com](http://www.example.com)**, **me.bob.com**, or **teleport.varrock.osrs**
***
## **Step 3: Add the CNAME and TXT record to your custom domain's DNS settings** [#step-3-add-the-cname-and-txt-record-to-your-custom-domains-dns-settings]
In your domain's DNS settings, create two **CNAME records** pointing your (sub)domain to **sell-beacon.net** These are the values for the record you should add:
1. **CNAME Record 1**
* **Host/Name:** \*
* **Value**/**Points To:** sell-beacon.net
2. **CNAME Record 2**
* **Host/Name:**
* **@** — If you'd like to link to your root domain *(as mentioned in point 1 above)*.
* **www**, or **me**, or **teleport** — If you'd like to link to your subdomain *(as mentioned in point 2 above)*.
* **Value**/**Points To:** sell-beacon.net
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.
3. **TXT Record**
* If your DNS provider is Cloudflare, you don't need to add a TXT record. The domain will be verified in a few moments and you'll be good to go. If your DNS provider is different *(i.e. NameCheap, GoDaddy, etc.)*, then you'll need to add an **\_acme-challenge** TXT record
* 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:** **\_acme-challenge.www** or **\_acme-challenge.me** or **\_acme-challenge.teleport**
* **Value/Points To:** The random string of characters shown on the SellApp page
At times, the TXT record is not required, so if it doesn't appear you should be OK to proceed with the rest of the setup steps.
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 **@** to value **sell-beacon.net** (**www**, or **me**, or **teleport** if it's a subdomain )
3. 1X TXT host pointing from just **\_acme-challenge** to value being the random string of characters shown on the SellApp page (**\_acme-challenge.www**, or **\_acme-challenge.me**, 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 an URL of your choosing once they have made payment and completed their purchase.
With SellApp, you can do so as follows: Create/Edit the relevant product -> navigate to the "Customization" section -> 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
Looking for a variable that's not in the above list? Send us a message by contacting us via live chat *(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 URL's and dynamic variables, you can verify whether the customer's order ID and email address correspond with a paid invoice, for example by pinging our API endpoint or storing incoming webhook data with our `order completed` webhooks, and let them 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 find yourself wanting 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 simply do so by appending the URL with the appropriate query string variables.
***
## 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
* `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]` The key and value of a checkout info field *(you can find 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 *(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&additional-4124bc0a9335c27f086f24ba207a4912=JohnDoe123`
***
## Embed modal variables [#embed-modal-variables]
If you are utilizing the embed modal, you can also pass along variables before initiating the modal. For more info, [click here to open the relevant documentation](/embedding-products#embed-variables)
# Dynamic webhook (/docs/setting-up-dynamic-webhook)
SellApp's dynamic webhook sends a `POST` requests to your webhook URL that you enter while creating a product.
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.
Whichever value you return to us as a response to the above `POST` request, we pass along to the customer.
SellApp only supports `HTTPS` webhook endpoints for security purposes.
***
## **Generating webhook secret** [#generating-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 "New Secret" in the "Webhook secret" section.
3. Once a secret is generated, click "Save" in order to save the newly generated webhook secret.
***
## **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.
SellApp uses the
`sha256`
hash function
Here is a validation example for the dynamic webhook endpoint in PHP:
```js
$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
}
```
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"
Once this has been set up and configured correctly, you're all good to go!
Whenever a new order gets created, we'll be pinging your dynamic endpoint URL you entered while creating the product, then pass along your webhook's response to the customer.
Happy selling!
# Stories (/docs/stories)
You've probably come across the "Stories" concept across various social media platforms *(like Instagram!)*: Stories are a powerful feature, and within SellApp, it is the key to help turn your store into a truly interactive experiences.
As a result, your store can experience a considerable lift in conversion rate. Now, 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** to immediately navigate to the product page *(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]
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. Upload up to 30 media files to your story. 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 sort media files to your liking, the story will play the media in the order you've sorted
5. 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, let's head on over to the builder to display your Stories block.
***
## Displaying Stories [#displaying-stories]
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. *(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.
# FAQ (/docs/faq)
This page covers the most common questions that are not answered elsewhere in the documentation.
## 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.
### 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 **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.
# Features (/docs/features)
Out of the box, SellApp includes a wide range of features to help you launch, sell, automate delivery, and grow your storefront.
## Core Platform Features [#core-platform-features]
* Digital product delivery with automatic fulfillment
* Built-in storefront hosting and customization
* Multiple payment method integrations
* Fraud protection and risk controls
* Discounting, promotions, and pricing tools
* Affiliate program support
* Subscription and recurring billing support
* Embedded checkout flows
* API access for programmatic integrations
## What You Can Build [#what-you-can-build]
With SellApp, you can sell software, ebooks, memberships, licenses, subscriptions, and other digital products through a single storefront.
## Related Guides [#related-guides]
Create your store, connect payments, and publish products.
Reach the support team when you need help with your store.
Review common operational questions and answers.
# Introduction (/docs)
SellApp is a powerful ecommerce platform for digital products. With SellApp, you can quickly set up an online store and sell digital goods worldwide. Tens of thousands of merchants use SellApp to power their online businesses.
## Getting Started [#getting-started]
SellApp is built for speed and simplicity. As your business grows, the platform grows with you. These pages cover the core setup flow, feature overview, support options, and common questions.
Learn how to create your store, connect payments, and list your first products.
Review the main platform capabilities available out of the box.
Find the fastest way to contact the SellApp support team.
Read the answers to common questions from merchants using SellApp.
# Setup Guide (/docs/setup)
Starting to sell on SellApp is simple. Most merchants can get through the initial 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, 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
Store name and visibility can be updated later. Store subdomains cannot currently be changed.
## Listing Your Products [#listing-your-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).
Customer payments are sent directly to your linked payment account. SellApp does not hold your funds.
Once a payment method is connected, you can immediately start creating products.
## Welcome to the Community [#welcome-to-the-community]
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 storefront, promotions, and automation.
If you need help at any point, use the live chat button on the site.
# Support (/docs/support)
Should you ever need help, the fastest way to contact SellApp is through live chat.
# Live Chat [#live-chat]
The fastest way to get in touch with the SellApp team is via live chat.
### 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 themselves. You can do so either by contacting them on any of 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 then appear at the bottom right of the page, please click it to open the live chat modal and initiate 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.
Abuse reports are only handled through email. Do not send them through social media or live chat.
# Introduction (/docs/storefront-builder-introduction)
The SellApp storefront builder gives you full control over your storefront's design and makes it possible to customize your storefront to your liking.
We have created the storefront builder with ease and simplicity in mind. You can utilize the builder without touching any code, and design your store with an easy and seamless drag & drop interface.
To get started with the builder, you will want to click the "Store Builder" button in the sidebar of the SellApp dashboard.
***
## The builder explained [#the-builder-explained]
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 is 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 overrode 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 the "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 **+** 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**
* **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]
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.
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, **simply click the "Publish" button at the top right.** 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. Happy selling!**
# API Reference (/docs/api)
The SellApp API lets you manage storefront data, automate workflows, and integrate your own tooling against the platform.
Learn how API keys are sent and how requests are authenticated.
Understand error responses and common failure modes.
Learn how paginated resource responses are structured.
Track the migration path for SDK and extension guidance.
Review webhook delivery behavior and payload handling guidance.
# Authorize.net (/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 our platform and API. Here's how.
***
## 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 ID" 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. 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 which already exist [#optionally-enabling-authorizenet-for-products-which-already-exist]
If you want to enable Authorize.net for products which 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. Click the "Update Payment Methods" button found in the "bulk update" dropdown that appears.
* A modal will pop up; check "Card (Authorize.net)" *(& 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.
# CashApp (/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 via our platform and API. Here's how.
***
## 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)
2. [Go to your account settings](https://cash.app/account/settings)
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]
Without the forwarding rule added, SellApp cannot detect or process Cash App payments automatically, so make sure to add it.
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 *(the 6th tab at the top)*
3. Click the "Add a forwarding address" button
4. In the modal that appears, enter `` as the forwarding address
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)
2. Click the blue "creating a filter!" text to open the filter modal
3. In the filter modal that pops up, enter `` in the "From" field, then click the "Create filter" button
4. In the next page, select the "Forward it to" option, and select `` as the forwarding address
5. Finally, click "Create filter"
***
## Step 3: Link Cash App to SellApp [#step-3-link-cash-app-to-sellapp]
The second 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, follow the steps. Make sure you enter **the email address you added to your Cash App in step 1**
3. Save the settings. 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 which already exist [#optionally-enabling-cash-app-for-products-which-already-exist]
If you want to enable Cash App for products which 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. Click the "Update Payment Methods" button found in the "bulk update" dropdown that appears.
* A modal will pop up; check Cash App *(& 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.
# Crypto (/docs/crypto)
Payments in crypto are becoming more and more prevalent, especially so for digital goods.
We've made it possible to directly link your crypto wallets to your SellApp storefront, helping you **earn crypto that directly gets deposited to your linked wallets**. No hold periods, no extra transaction fees, and no withdrawal fees.
***
## Linking Wallets [#linking-wallets]
1. Navigate to [your storefront payment settings by clicking here](https://sell.app/dashboard/settings?settings=payment).
2. You will find a "Cryptocurrencies" section. Click on the relevant cryptocurrency you'd like to link to display a setup modal.
3. Enter your wallet address or XPUB key
1. If you are linking Litecoin or Bitcoin, you need to get an XPUB. Don't know how to do so? [Navigate to the support article by clicking here](#support-how-to-find-extended-public-key-xpub-for-bitcoin-and-or-litecoin)
* The xpub does not necessarily start with "xpub...", it can also start with "zpub..." or "ypub...". If that's the case, just copy/paste the relevant value from your wallet to the modal and save. It will work without an issue.
2. If you are linking Monero, it requires a Monero address to be entered, as well as your wallet's "Private View Key"
3. If you are linking any of the other wallets, just copy/paste your wallet address and you'll be good to go
4. Finally, click "Save" in the modal
That's it! Your crypto wallet has now been enabled for your store, you can enable it as a payment method for every new product you create.
***
## Optionally: Enabling crypto for products which already exist [#optionally-enabling-crypto-for-products-which-already-exist]
If you want to enable crypto for products which 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 crypto for.
3. Click the "Update Payment Methods" button found in the "bulk update" dropdown that appears.
* A modal will pop up; check the relevant crypto option *(, as well as all 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 crypto enabled as a payment method, which customers will be able to select when making a purchase.
***
## Support: How to find Extended Public Key *(XPUB)* for Bitcoin and/or Litecoin [#support-how-to-find-extended-public-key-xpub-for-bitcoin-andor-litecoin]
For certain crypto, SellApp generates new payment addresses for every order created. These addresses are generated via the extended public key (xpub/zpub/ypub) that you link to your store.
The benefits of linking an XPUB to your SellApp store:
1. SellApp does not require access to your private keys, meaning there is zero risk of something going wrong.
2. Bitcoin/Litecoin payments go directly to your wallet, we don't hold funds or charge double the transaction fees.
3. Enhanced privacy as every new order created generates a fresh address
We **strongly** recommend using either Exodus or Electrum. **Other wallets, such as Ledger, are known to cause issues** and **may result in funds not being accessible** unless you're technical
**Where to find xpub in Exodus:**
When exporting your XPUB from Exodus for Bitcoin, **make sure to use the second XPUB in the list, which starts with a ZPUB**
1. Open your Exodus desktop wallet app *(Note, the mobile wallet does not have this option)*
2. Navigate to the Bitcoin or Litecoin wallet in the app
3. Click the three dots at the top right, then select "Export XPUB" to download your xpub/zpub/ypub key.
4. Copy the xpub/zpub/ypub key from the exported file and paste it [into your SellApp Bitcoin/Litecoin wallet settings](https://sell.app/dashboard/settings?settings=payment)
* **Copy and paste the second option for Bitcoin, which starts with a ZPUB**
**Where to find xpub in Electrum Wallet:**
1. Open your Electrum app.
2. Navigate to "Wallet" -> "Information".
3. A modal will appear. The second text area should be titled as "Master Public Key". In the text area itself, it should show your public key that starts with "xpub", "zpub", or "ypub"
4. Copy the xpub/zpub/ypub key and paste it [into your SellApp Bitcoin/Litecoin wallet settings](https://sell.app/dashboard/settings?settings=payment)
**Where to find xpub in Coinbase, Binance, Trust Wallet, Kraken, etc.:**
These providers hold funds on your behalf, so you don't have an actual wallet with them. This means that you can't retrieve an "xpub", "zpub", or "ypub" key from them.
If this is the case, we'd recommend downloading [Electrum](https://electrum.org) or [Exodus](https://exodus.com/) to use as your SellApp wallet.
***
## Support: I didn't receive the funds in my wallet [#support-i-didnt-receive-the-funds-in-my-wallet]
There are two possible reasons why you don't see the funds you've received:
1. You manually marked an order as completed. **orders should never be marked as completed unless you're absolutely certain you've received the funds**
2. You copy/pasted an XPUB from a wallet other than Electrum/Exodus
In the first case, this is an user error as funds might never have been sent by the customer. We cannot assist in this scenario, as the payment very likely does not exist.
In the second case, you will want to export your seed and import it into [Electrum](https://electrum.org). Then, you'd need to scan the derivations and/or set the derivation path manually.
To see what derivation path your funds are in, we suggest using the following Trezor link: [https://btc1.trezor.io/xpub/EnterYourXpubHere](https://btc1.trezor.io/xpub/EnterYourXpubHere)
The above link will show all of the payments your XPUB has received, and the derivation path for each address.
# Paddle (/docs/paddle)
SellApp makes it very easy to link your [Paddle](https://paddle.com/) account and start accepting PayPal, credit/debit card, and other payment types for your digital products. Here's how.
***
## Adding our webhook [#adding-our-webhook]
First, we need to add the SellApp webhook endpoint to your Paddle account. **Without it added, payments will not automatically process.** Here's how to do so:
1. Go to your Paddle events settings, [you can do so by clicking here](https://vendors.paddle.com/alerts-webhooks).
2. Enter `https://sell.app/paddle/webhook` in the "webhook URL" input, found in the `URLs for receiving webhooks` section.
* *Note: Don't visit this URL directly, it will display an error page. Just copy/paste the URL in the modal and you're good to go.*
3. Scroll down to the "One-off purchases" section, and toggle on all events: `Payment Success`, `Payment Refunded`, `Order Processing Completed` *(the webhook option on the right, not the email one)*.
Without the above webhook URL added and events toggled on, SellApp cannot detect or process Paddle payments automatically, so make sure to add it first.
***
## Linking Paddle [#linking-paddle]
Now that the webhook endpoint has been added and events have been enabled, we can start linking Paddle to your SellApp storefront. Here's how to do so:
1. Navigate to [your storefront payment settings by clicking here](https://sell.app/dashboard/settings?settings=payment).
2. You will find a "Paddle" button. click it to open the modal which displays **three** input fields: "**Vendor ID**", "**Vendor Auth Code**", "**Public key**".
1. [You can find your Vendor ID and Vendor Auth Code by clicking here](https://vendors.paddle.com/authentication).
1. If you don't have an auth code, you can click "Generate Key" to generate a new auth code
2. Click "Reveal auth code" to display your auth code, copy the value and paste it into our "Vendor Auth Code" input
3. At the top of the page you will find "Your Paddle Vendor ID". Copy and past the ID into our "Vendor ID" input
2. [You can find your public key by clicking here](https://vendors.paddle.com/public-key).
1. Copy the value displayed on Paddle's page *(The entire thing, from "BEGIN PUBLIC KEY, to END PUBLIC KEY")*
2. Paste it into our "Public key" input
3. 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.
***
## Optionally: Enabling Paddle for products which already exist [#optionally-enabling-paddle-for-products-which-already-exist]
If you want to enable Paddle for products which 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. Click the "Update Payment Methods" button found in the "bulk update" dropdown that appears.
* A modal will pop up; check Paddle *(& 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.
# Introduction (/docs/payment-methods-introduction)
Wondering where and how you can add/remove payment methods, or have payment-related questions? This page will help you.
***
## 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:
Accept credit and debit card payments through Authorize.net.
Configure Cash App and email forwarding so payments process automatically.
Link wallets and XPUBs for supported cryptocurrency payments.
Connect Paddle and register the SellApp webhook endpoint.
Link PayPal directly or enable it with your PayPal email address.
Add your Square access token and location ID.
Complete Stripe onboarding and enable it for your products.
***
## 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 *(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. Select the "Bulk Update" dropdown and then click "Update Payment Methods"
4. Toggle the payment methods you would like to accept on *(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]
SellApp does not hold your money or makes you wait until a specific payout date for your earned funds.
The customer does not pay our account, but instead the money is immediately sent from them to your linked payment processor account.
This means that whenever a sale is made, you instantly get access to the funds.
# PayPal (/docs/paypal)
SellApp makes it very easy to link your [PayPal](https://www.paypal.com/) account and start accepting PayPal payments for your digital products. Here's how.
***
## 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, a modal will appear displaying a "**Connect with PayPal button**". When you click it, you will be redirected to PayPal and asked if you want to give SellApp the respective permissions.
3. When you are redirected back to SellApp, your PayPal account will have successfully been linked with your store.
4. *Optional:* If you don't want to to link your PayPal account directly, you can also simply enter your PayPal email address in step 2 and click "Save"
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 which already exist [#optionally-enabling-paypal-for-products-which-already-exist]
If you want to enable PayPal for products which 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. Click the "Update Payment Methods" button found in the "bulk update" dropdown that appears.
* A modal will pop up; check PayPal *(& 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's 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 *(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.
# Square (/docs/square)
SellApp makes it very easy to link your [Square](https://square.com/) account and start accepting PayPal, credit/debit card, and other payment types for your digital products. Here's how.
***
## 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. Paste the above values in the respective inputs and save the settings by clicking "Save" in the SellApp modal
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 which already exist [#optionally-enabling-square-for-products-which-already-exist]
If you want to enable Square for products which 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. Click the "Update Payment Methods" button found in the "bulk update" dropdown that appears.
* A modal will pop up; check Square *(& 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 (/docs/stripe)
SellApp makes it very easy to link your [Stripe](https://stripe.com/) account and start accepting card payments for your digital products. Here's how.
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.
***
## 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 onboarding 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 "Onboarding Completed".
2. Finally, click "Enable" in the modal
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 which already exist [#optionally-enabling-stripe-for-products-which-already-exist]
If you want to enable Stripe for products which 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. Click the "Update Payment Methods" button found in the "bulk update" dropdown that appears.
* A modal will pop up; check Stripe *(& 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!
# Authentication (/docs/api/authentication)
You'll need to authenticate your requests to access any of the endpoints in the
SellApp API. SellApp currently offers one way to authenticate API requests:
using a secret API key.
## Authentication with a secret API key [#authentication-with-a-secret-api-key]
Authenticating with the SellApp API is done by passing your secret API key in
the request headers.
```bash title="Example request with bearer token"
curl --request GET \
--url 'https://sell.app/api/v1/invoices' \
--header 'Authorization: Bearer {ApiKeyHere}' \
--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 are tied to an account, not a storefront. While you can toggle API
permissions on or off while creating an API key, access to resources still
depends on what permissions your account has on the storefront you are
interacting with.
As the owner of a storefront, you will always have full access to all API
endpoints, provided the relevant permissions were enabled when the key was
created.
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.
## Multiple stores [#multiple-stores]
If your account belongs to multiple storefronts, you can pass an `X-STORE`
header to specify which store you want to access. If you do not own any stores
or do not pass the header, the API defaults to the first store you own or
joined.
If you want to access `bob.sell.app`, you would pass the slug `bob` via the
`X-STORE` header:
```bash title="Example request accessing bob.sell.app invoices"
curl --request GET \
--url 'https://sell.app/api/v1/invoices' \
--header 'Authorization: Bearer {ApiKeyHere}' \
--header 'X-STORE: bob' \
--header 'Content-Type: application/json'
```
## Using an SDK [#using-an-sdk]
If you use an SDK, you do not need to manage most of the request setup
yourself. Fetch your API key from your developers settings, then let the client
library handle the authentication headers and request plumbing for you.
For currently known packages and integrations, see [SDKs &
Extensions](/api/sdks).
# Errors (/docs/api/errors)
What happens when something goes wrong while you are interacting with the API?
Mistakes happen, so this guide covers the status codes and error types you may
encounter.
Before reaching out to support with an issue, carefully check your code for
incorrectly typed variables and missing or malformed headers.
You can tell if a request was successful by checking the HTTP status code on the
response. If a response is unsuccessful, use the error type and message to
understand what went wrong and to debug the request.
***
## Status codes [#status-codes]
Here are the status code categories returned by the SellApp API:
A `2xx` status code indicates a successful response.
A `4xx` status code indicates a client error.
A `5xx` status code indicates a server error.
***
## Error types [#error-types]
Whenever a request is unsuccessful, the SellApp API returns an error response
with an error type and message. Use this information to understand what went
wrong and how to fix it.
The list of error codes may grow over time. The following code is currently
documented in the legacy API reference:
This means either the API key passed along is incorrectly formatted, or you
are missing a required header.
# Pagination (/docs/api/pagination)
SellApp API list responses are paginated. By default, responses limit results to
fifteen items. You can increase that limit up to one hundred by adding a
`limit` query parameter to your request.
Whenever an API response returns a list of objects, pagination is supported. Use
the `page` query parameter to browse result pages.
## Example using invoices [#example-using-invoices]
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 response limit of the API resource you are accessing.
The page number you are attempting to access.
```bash title="Manual pagination using cURL"
curl --request GET \
--url 'https://sell.app/api/v1/invoices?page=10&limit=20' \
--header 'Authorization: Bearer {ApiKeyHere}' \
--header 'Content-Type: application/json'
```
```json title="Paginated response"
{
"data": [
{
"id": "1"
},
{
"id": "2"
},
{
"id": "3"
}
],
"meta": {
"current_page": 10,
"from": 181,
"last_page": 42,
"links": [
// ...
]
}
}
```
# SDKs & Extensions (/docs/api/sdks)
SellApp and its community have created API libraries and extensions to make it
easier to integrate with the platform.
We are working toward releasing official packages and integrations, starting
with a WooCommerce plugin for creating charges. We currently do not offer
official SDKs for every language, but members of the SellApp community have
created a handful of open-source packages that may be useful depending on your
stack.
Community packages listed here are not officially endorsed. They are included
because they are open-source and may be useful for your use case.
## Community SDKs & extensions [#community-sdks--extensions]
The official WooCommerce plugin for SellApp.
A community-maintained Node.js wrapper for the SellApp API.
A community-maintained Python package for interacting with SellApp.
A community-maintained .NET integration for SellApp.
A community-maintained React integration for SellApp storefront flows.
***
## 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.
# Webhooks (/docs/api/webhooks)
Webhooks let your application react when something happens in SellApp, such as
an order being completed or a support ticket receiving a new 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.
## 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.
```json title="Example webhook payload"
{
"event": "order.completed",
"data": {
"id": 236
},
"store": 1
}
```
In the example above, an order was `completed`, and the payload type is
`order`.
***
## Event types [#event-types]
A CashApp payment is pending.
A new feedback was created.
A new order was created.
An existing order was paid.
A paid order was disputed.
A new product was created.
An existing product was updated.
A product was successfully deleted.
A new ticket message was created.
A new product variant was created.
An existing product variant was updated.
An existing product variant ran out of stock.
```json title="Example payload"
{
"event": "ticket_message.created",
"data": {
"author": "CUSTOMER",
"sender": "mark@meta.com",
"content": "Hey, I'm interested in investing.",
"ticket_id": 1337,
"updated_at": "2022-04-20T13:37:69.000000Z",
"created_at": "2022-04-20T13:37:69.000000Z",
"id": 6969,
"ticket": {
"id": 1337,
"title": "Acquisition",
"status": "OPEN",
"customer": {
"id": "c4e45131-a187-3476-9efd-1fb6fbbf2243",
"email": "mark@meta.com"
},
"reference": {
"id": 87654,
"type": "App\\Models\\Invoice"
},
"created_at": "2022-04-20T13:37:69.000000Z",
"updated_at": "2022-04-20T13:37:69.000000Z",
"store_id": 1,
"read_by": 1,
"archived": 0
}
},
"store": 1
}
```
***
## Security [#security]
To verify that a webhook really came from SellApp and not from a malicious
sender, validate the request signature. 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.
Each webhook request contains a `signature` header. You can verify that
signature by hashing the raw request payload with your secret webhook key using
HMAC SHA-256.
JavaScript
Python
PHP
```js
const signature = req.headers['signature'];
const hash = crypto.createHmac('sha256', secret).update(payload).digest('hex');
if (hash === signature) {
// Request has been verified
} else {
// Request could not be verified
}
```
```python
from flask import request
import hashlib
import hmac
signature = request.headers.get("signature")
hash = hmac.new(bytes(secret, "ascii"), bytes(payload, "ascii"), hashlib.sha256)
if hash.hexdigest() == signature:
# Request has been verified
else:
# Request could not be verified
```
```php
$signature = $request['headers']['signature'];
$hash = hash_hmac('sha256', $payload, $secret);
if (hash_equals($hash, $signature)) {
// Request has been verified
} else {
// Request could not be verified
}
```
If your generated signature matches the `signature` header, you can be sure the
request came from SellApp. Keep your secret webhook key safe. If it leaks, you
can no longer trust the signature.
## 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 channels support the same types of events as
traditional webhook events. For setup instructions, see the [creating
notifications](/creating-notifications) guide.
# Create a Blacklist Rule (/docs/api/blacklists/create-blacklist)
Create a new blacklist rule for your store.
## Endpoint
- Method: `POST`
- Path: `/v1/blacklists`
- Full URL: `https://sell.app/api/v1/blacklists`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
None.
## Query Parameters
None.
## Header Parameters
None.
## 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": "@yahoo.com"
},
"description": {
"type": "string",
"description": "Why this rule is being created.",
"example": "This email domain is dangerous"
}
},
"example": {
"type": "WILDCARD_EMAIL",
"data": "@yahoo.com",
"description": "This email domain is dangerous"
}
}
```
Example:
```json
{
"type": "WILDCARD_EMAIL",
"data": "@yahoo.com",
"description": "This email domain is dangerous"
}
```
## Responses
### 200
The newly created blacklist rule.
#### 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": "rick@astley.com"
},
"description": {
"type": "string",
"description": "Why this blacklist rule exists.",
"example": "He rickrolled me too many times."
},
"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": "@yahoo.com",
"description": "This email domain is dangerous",
"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": "@yahoo.com",
"description": "This email domain is dangerous",
"created_at": "2022-12-12T12:12:12.000000Z",
"updated_at": "2022-12-12T12:12:12.000000Z",
"store_id": 1
}
}
```
### 401
Authentication failed.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Unauthenticated."
}
}
}
```
### 422
The request payload failed validation.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "The given data was invalid."
},
"errors": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
},
"example": {
"data": [
"The data field is required."
]
}
}
}
}
```
# Delete a Blacklist Rule (/docs/api/blacklists/delete-blacklist)
Permanently delete a blacklist rule from your store.
## Endpoint
- Method: `DELETE`
- Path: `/v1/blacklists/{blacklist}`
- Full URL: `https://sell.app/api/v1/blacklists/{blacklist}`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `blacklist` (`integer`, required): The unique identifier of the blacklist rule.
## Query Parameters
None.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
The blacklist rule was deleted successfully.
#### 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": "rick@astley.com"
},
"description": {
"type": "string",
"description": "Why this blacklist rule exists.",
"example": "He rickrolled me too many times."
},
"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": "@yahoo.com",
"description": "This email domain is dangerous",
"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": "@yahoo.com",
"description": "This email domain is dangerous",
"created_at": "2022-12-12T12:12:12.000000Z",
"updated_at": "2022-12-12T12:12:12.000000Z",
"store_id": 1
}
}
```
### 401
Authentication failed.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Unauthenticated."
}
}
}
```
### 404
The requested blacklist rule was not found.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Blacklist rule not found."
}
}
}
```
# Overview (/docs/api/blacklists)
Blacklist rules help prevent your SellApp storefront from falling victim to
malicious users. They allow you to block fraud attempts by preventing purchases
when customer details match one of your blacklist rules.
This section breaks each blacklist endpoint into its own page so every
operation has a dedicated URL and can be indexed independently.
## Endpoints [#endpoints]
* [List all blacklist rules](/api/blacklists/list-blacklists)
* [Create a blacklist rule](/api/blacklists/create-blacklist)
* [Retrieve a blacklist rule](/api/blacklists/retrieve-blacklist)
* [Update a blacklist rule](/api/blacklists/update-blacklist)
* [Delete a blacklist rule](/api/blacklists/delete-blacklist)
***
## The blacklist model [#the-blacklist-model]
The blacklist model contains the information storefront purchase attempts are
checked against, including the rule type, the rule data, and an internal
description.
### Properties [#properties]
Unique identifier for the blacklist rule.
The type of blacklist rule. Supported types:
* `ASN`
* `COUNTRY`
* `EMAIL`
* `IP`
* `WILDCARD_EMAIL`
The data related to the rule type. Examples:
* `ASN`: `AS1234`
* `COUNTRY`: `BE`
* `EMAIL`: `rick@astley.com`
* `IP`: `1.3.3.7`
* `WILDCARD_EMAIL`: `@yahoo.com`
The description of why this blacklist rule was created.
The time at which this blacklist rule was first created.
The time at which this blacklist rule was last updated.
The ID of the store this blacklist rule belongs to.
# List All Blacklist Rules (/docs/api/blacklists/list-blacklists)
Retrieve a paginated list of blacklist rules.
## Endpoint
- Method: `GET`
- Path: `/v1/blacklists`
- Full URL: `https://sell.app/api/v1/blacklists`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
None.
## Query Parameters
- `limit` (`integer`, optional): Limit the number of blacklist rules returned.
- `page` (`integer`, optional): The page number you are attempting to access.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
A paginated list of blacklist rules.
#### 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": "rick@astley.com"
},
"description": {
"type": "string",
"description": "Why this blacklist rule exists.",
"example": "He rickrolled me too many times."
},
"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",
"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",
"properties": {
"current_page": {
"type": "integer",
"example": 1
},
"from": {
"type": "integer",
"example": 1
},
"last_page": {
"type": "integer",
"example": 4
},
"path": {
"type": "string",
"example": "https://sell.app/api/v1/blacklists"
},
"per_page": {
"type": "integer",
"example": 15
},
"to": {
"type": "integer",
"example": 15
},
"total": {
"type": "integer",
"example": 57
}
}
}
},
"example": {
"data": [
{
"id": 1,
"type": "EMAIL",
"data": "rick@astley.com",
"description": "He rickrolled me too many times.",
"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": "rick@astley.com",
"description": "He rickrolled me too many times.",
"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
}
}
```
### 401
Authentication failed.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Unauthenticated."
}
}
}
```
# Retrieve a Blacklist Rule (/docs/api/blacklists/retrieve-blacklist)
Retrieve a specific blacklist rule by its unique identifier.
## Endpoint
- Method: `GET`
- Path: `/v1/blacklists/{blacklist}`
- Full URL: `https://sell.app/api/v1/blacklists/{blacklist}`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `blacklist` (`integer`, required): The unique identifier of the blacklist rule.
## Query Parameters
None.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
The requested blacklist rule.
#### 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": "rick@astley.com"
},
"description": {
"type": "string",
"description": "Why this blacklist rule exists.",
"example": "He rickrolled me too many times."
},
"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": "@yahoo.com",
"description": "This email domain is dangerous",
"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": "@yahoo.com",
"description": "This email domain is dangerous",
"created_at": "2022-12-12T12:12:12.000000Z",
"updated_at": "2022-12-12T12:12:12.000000Z",
"store_id": 1
}
}
```
### 401
Authentication failed.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Unauthenticated."
}
}
}
```
### 404
The requested blacklist rule was not found.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Blacklist rule not found."
}
}
}
```
# Update a Blacklist Rule (/docs/api/blacklists/update-blacklist)
Update one or more attributes on an existing blacklist rule.
## Endpoint
- Method: `PATCH`
- Path: `/v1/blacklists/{blacklist}`
- Full URL: `https://sell.app/api/v1/blacklists/{blacklist}`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `blacklist` (`integer`, required): The unique identifier of the blacklist rule.
## Query Parameters
None.
## Header Parameters
None.
## 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": "@yahoomail.com"
},
"description": {
"type": "string",
"description": "The updated reason for this rule.",
"example": "This email domain is super dangerous"
}
},
"example": {
"type": "WILDCARD_EMAIL",
"data": "@yahoomail.com",
"description": "This email domain is super dangerous"
}
}
```
Example:
```json
{
"type": "WILDCARD_EMAIL",
"data": "@yahoomail.com",
"description": "This email domain is super dangerous"
}
```
## Responses
### 200
The updated blacklist rule.
#### 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": "rick@astley.com"
},
"description": {
"type": "string",
"description": "Why this blacklist rule exists.",
"example": "He rickrolled me too many times."
},
"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": "@yahoo.com",
"description": "This email domain is dangerous",
"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": "@yahoo.com",
"description": "This email domain is dangerous",
"created_at": "2022-12-12T12:12:12.000000Z",
"updated_at": "2022-12-12T12:12:12.000000Z",
"store_id": 1
}
}
```
### 401
Authentication failed.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Unauthenticated."
}
}
}
```
### 404
The requested blacklist rule was not found.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Blacklist rule not found."
}
}
}
```
### 422
The request payload failed validation.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "The given data was invalid."
},
"errors": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
},
"example": {
"data": [
"The data field is required."
]
}
}
}
}
```
# Create a charge (/docs/api/charges/create-a-charge)
This endpoint allows you to create a new charge object. This can be for a paid transaction or a free item claim.
## Endpoint
- Method: `POST`
- Path: `/v2/charges`
- Full URL: `https://sell.app/api/v2/charges`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
None.
## Query Parameters
None.
## Header Parameters
None.
## 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",
"format": "uri"
},
"webhook": {
"type": "string",
"format": "uri"
},
"reference": {
"type": "string"
},
"description": {
"type": "string"
},
"currency": {
"type": "string"
},
"total": {
"type": "integer"
},
"payment_method": {
"type": "string",
"enum": [
"AUTHNET",
"BTCPAY",
"CASHAPP",
"COINBASE",
"PADDLE",
"PAYDASH",
"PAYPAL",
"PAYSTACK",
"SQUARE",
"STRIPE",
"VENMO",
"NMI",
"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",
"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"
]
}
},
"use_all_payment_methods": {
"type": "boolean"
},
"deliverable": {
"type": "object",
"additionalProperties": true
},
"metadata": {
"type": "object",
"additionalProperties": true
},
"coupon_code": {
"type": "string"
}
},
"required": [
"email",
"return_url"
]
}
```
Example:
```json
{
"email": "customer@example.com",
"return_url": "https://store.com/thank-you",
"currency": "USD",
"total": 10000,
"payment_method": "PAYPAL",
"reference": "Test Payment"
}
```
## Responses
### 200
Successful response.
#### 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"
}
}
```
# Overview (/docs/api/charges)
Charges are a slimmed down, more fluid, version of orders. Similar to orders, they are used to take payment for products/services rendered. Unlike orders, however, charges do not manage/handle product delivery.
This makes charges especially useful as a building block for your external project where you handle/manage product delivery manually.
On this page, we'll dive into the different charge endpoints you can use to manage charges programmatically. We'll look at how to view, create, and update charges.
## Endpoints [#endpoints]
* [Create a charge](/api/charges/create-a-charge)
* [Retrieve a charge](/api/charges/retrieve-a-charge)
* [Mark pending charge completed](/api/charges/mark-pending-charge-completed)
* [Mark pending charge voided](/api/charges/mark-pending-charge-voided)
## The charge model [#the-charge-model]
The charge model contains all the information about the charges stores have, including the type, code, and discount amount.
### Properties [#properties]
*(read-only)* The unique identifier for the Charge object.
*(read-only)* The checkout URL you would direct a customer to. The customer can complete the payment or claim the free item on this URL.
*(read-only)* The current status of the charge. Possible values include `PENDING`, `COMPLETED`, `VOIDED`.
The customer's email address. **Required**.
*(optional)* An optional reference for the charge.
*(conditional)* Three-letter ISO currency code. **Required** if `total` > 0.
*(conditional)* The total amount intended to be charged in the smallest currency unit (e.g., cents for USD). **Required** if `currency` is provided and the charge is not free. Must be > 0 for paid charges.
The URL to redirect the customer back to after they complete the checkout process (successfully or not). **Required**.
*(optional)* A URL to send webhook events to for status updates regarding this charge.
*(conditional)* The specific payment gateway(s) for this charge. **Required** for paid charges. You can either pass:
1. One payment method: `"payment_method": "STRIPE"`
2. Multiple payment methods (which the customer can select from): `"payment_methods": ["PAYPAL", "STRIPE"]`
3. All payment methods configured on your SellApp store: `"use_all_payment_methods": true`
*(optional)* A URL to redirect the customer to if they cancel the checkout process.
*(optional)* An optional description for the charge.
*(optional)* A valid SellApp coupon code to apply to the charge.
*(read-only)* Time at which the object was created.
*(read-only)* Time at which the object was last updated.
**Note on Amounts:** All monetary amounts (like `total`) are provided in the smallest currency unit (e.g., cents for USD, pence for GBP).
***
# Mark pending charge completed (/docs/api/charges/mark-pending-charge-completed)
Manually marks a pending charge as completed.
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.
## Endpoint
- Method: `PUT`
- Path: `/v2/charges/{charge_id}/completed`
- Full URL: `https://sell.app/api/v2/charges/{charge_id}/completed`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `charge_id` (`integer`, required): The charge id path parameter.
## Query Parameters
None.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
Successful response.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"message": {
"type": "string"
}
},
"required": [
"message"
]
}
```
Example:
```json
{
"message": "Charge Completed Successfully"
}
```
# Mark pending charge voided (/docs/api/charges/mark-pending-charge-voided)
Manually marks a pending charge as voided (canceled).
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.
## Endpoint
- Method: `PUT`
- Path: `/v2/charges/{charge_id}/voided`
- Full URL: `https://sell.app/api/v2/charges/{charge_id}/voided`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `charge_id` (`integer`, required): The charge id path parameter.
## Query Parameters
None.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
Successful response.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"message": {
"type": "string"
}
},
"required": [
"message"
]
}
```
Example:
```json
{
"message": "Charge Voided Successfully"
}
```
# Retrieve a charge (/docs/api/charges/retrieve-a-charge)
Retrieves the details of an existing charge by its ID. Refer to [the charge model](#the-charge-model) section for details on the returned object structure.
## Endpoint
- Method: `GET`
- Path: `/v2/charges/{charge}`
- Full URL: `https://sell.app/api/v2/charges/{charge}`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `charge` (`integer`, required): The charge path parameter.
## Query Parameters
None.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
Successful response.
#### 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"
}
}
```
# Create a coupon (/docs/api/coupons/create-a-coupon)
This endpoint allows you to create a new coupon. See the code examples for how to create a new coupon with the SellApp API.
## Endpoint
- Method: `POST`
- Path: `/v1/coupons`
- Full URL: `https://sell.app/api/v1/coupons`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
None.
## Query Parameters
None.
## Header Parameters
None.
## Request Body
- Required: Yes
### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"code": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"PERCENTAGE",
"AMOUNT"
]
},
"discount": {
"type": "number"
},
"store_wide": {
"type": "boolean"
},
"products": {
"type": "array",
"minItems": 1,
"items": {
"type": "integer"
}
},
"limit": {
"type": [
"integer",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"minimum_amount": {
"type": [
"number",
"null"
]
}
},
"required": [
"code",
"type",
"discount",
"store_wide"
]
}
```
## Responses
### 200
Successful response.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"code": {
"type": "string"
},
"type": {
"type": "string"
},
"discount": {
"type": "string"
},
"limit": {
"type": "null"
},
"store_wide": {
"type": "boolean"
},
"minimum_amount": {
"type": "null"
},
"expires_at": {
"type": "null"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"store_id": {
"type": "integer"
},
"deleted_at": {
"type": "null"
}
},
"required": [
"id",
"code",
"type",
"discount",
"limit",
"store_wide",
"minimum_amount",
"expires_at",
"created_at",
"updated_at",
"store_id",
"deleted_at"
]
}
},
"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
}
}
```
# Delete a coupon (/docs/api/coupons/delete-a-coupon)
This endpoint allows you to delete a coupon.
This will permanently delete the coupon.
## Endpoint
- Method: `DELETE`
- Path: `/v1/coupons/{coupon}`
- Full URL: `https://sell.app/api/v1/coupons/{coupon}`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `coupon` (`integer`, required): The coupon path parameter.
## Query Parameters
None.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
Successful response.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"code": {
"type": "string"
},
"type": {
"type": "string"
},
"discount": {
"type": "string"
},
"limit": {
"type": "null"
},
"store_wide": {
"type": "boolean"
},
"minimum_amount": {
"type": "null"
},
"expires_at": {
"type": "null"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"store_id": {
"type": "integer"
},
"deleted_at": {
"type": "null"
}
},
"required": [
"id",
"code",
"type",
"discount",
"limit",
"store_wide",
"minimum_amount",
"expires_at",
"created_at",
"updated_at",
"store_id",
"deleted_at"
]
}
},
"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
}
}
```
# Overview (/docs/api/coupons)
Coupons help boost sales on your SellApp storefront — they allow you to attract new customers with exclusive offers and reward existing customers for their previous purchases.
On this page, we'll dive into the different coupon endpoints you can use to manage coupons programmatically. We'll look at how to create, update, and delete coupons.
## Endpoints [#endpoints]
* [List all coupons](/api/coupons/list-all-coupons)
* [Create a coupon](/api/coupons/create-a-coupon)
* [Retrieve a coupon](/api/coupons/retrieve-a-coupon)
* [Update a coupon](/api/coupons/update-a-coupon)
* [Delete a coupon](/api/coupons/delete-a-coupon)
## The coupon model [#the-coupon-model]
The coupon model contains all the information about the coupons stores have, including the type, code, and discount amount.
### Properties [#properties]
The unique identifier for the coupon.
The coupon code which the customer enters during checkout.
The type of coupon. Supported types:
* PERCENTAGE
* AMOUNT
The discount value related to the above type. Examples:
* PERCENTAGE: `50` *(in percentages)*
* AMOUNT: `5` *(in dollars)*
The total amount of times this coupon can be applied before it can no longer be used.
The scope of the coupon; if true it applies to all products in your store. If false, it only applies to certain products.
The minimum amount *(in dollars)* at which the coupon can be applied.
The time at which this coupon stops being usable.
The time at which this coupon was first created.
The time at which this coupon was last updated.
The ID of the store this coupon belongs to.
The time at which this coupon was deleted.
***
# List all coupons (/docs/api/coupons/list-all-coupons)
This endpoint allows you to retrieve a paginated list of all your coupons. By default, a maximum of fifteen coupons are shown per page.
## Endpoint
- Method: `GET`
- Path: `/v1/coupons`
- Full URL: `https://sell.app/api/v1/coupons`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
None.
## Query Parameters
- `limit` (`integer`, optional): Limit the number of blacklist rules returned.
- `page` (`integer`, optional): The page number you are attempting to access.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
Successful response.
#### 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"
},
"discount": {
"type": "string"
},
"limit": {
"type": "null"
},
"store_wide": {
"type": "boolean"
},
"minimum_amount": {
"type": "null"
},
"expires_at": {
"type": "null"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"store_id": {
"type": "integer"
},
"deleted_at": {
"type": "null"
}
},
"required": [
"id",
"code",
"type",
"discount",
"limit",
"store_wide",
"minimum_amount",
"expires_at",
"created_at",
"updated_at",
"store_id",
"deleted_at"
]
}
},
"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
}
],
"links": {},
"meta": {}
}
```
# Retrieve a coupon (/docs/api/coupons/retrieve-a-coupon)
This endpoint allows you to retrieve a specific coupon by providing the unique identifier. Refer to [the list](/api/coupons#the-coupon-model) to see which properties are included with coupon objects.
## Endpoint
- Method: `GET`
- Path: `/v1/coupons/{coupon}`
- Full URL: `https://sell.app/api/v1/coupons/{coupon}`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `coupon` (`integer`, required): The coupon path parameter.
## Query Parameters
None.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
Successful response.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"code": {
"type": "string"
},
"type": {
"type": "string"
},
"discount": {
"type": "string"
},
"limit": {
"type": "null"
},
"store_wide": {
"type": "boolean"
},
"minimum_amount": {
"type": "null"
},
"expires_at": {
"type": "null"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"store_id": {
"type": "integer"
},
"deleted_at": {
"type": "null"
}
},
"required": [
"id",
"code",
"type",
"discount",
"limit",
"store_wide",
"minimum_amount",
"expires_at",
"created_at",
"updated_at",
"store_id",
"deleted_at"
]
}
},
"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
}
}
```
# Update a coupon (/docs/api/coupons/update-a-coupon)
This endpoint allows you to perform an update on a coupon.
## Endpoint
- Method: `PATCH`
- Path: `/v1/coupons/{coupon}`
- Full URL: `https://sell.app/api/v1/coupons/{coupon}`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `coupon` (`integer`, required): The coupon path parameter.
## Query Parameters
None.
## Header Parameters
None.
## Request Body
- Required: Yes
### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"code": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"PERCENTAGE",
"AMOUNT"
]
},
"discount": {
"type": "number"
},
"store_wide": {
"type": "boolean"
},
"products": {
"type": "array",
"minItems": 1,
"items": {
"type": "integer"
}
},
"limit": {
"type": [
"integer",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"minimum_amount": {
"type": [
"number",
"null"
]
}
}
}
```
## Responses
### 200
Successful response.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"code": {
"type": "string"
},
"type": {
"type": "string"
},
"discount": {
"type": "string"
},
"limit": {
"type": "null"
},
"store_wide": {
"type": "boolean"
},
"minimum_amount": {
"type": "null"
},
"expires_at": {
"type": "null"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"store_id": {
"type": "integer"
},
"deleted_at": {
"type": "null"
}
},
"required": [
"id",
"code",
"type",
"discount",
"limit",
"store_wide",
"minimum_amount",
"expires_at",
"created_at",
"updated_at",
"store_id",
"deleted_at"
]
}
},
"required": [
"data"
]
}
```
Example:
```json
{
"data": {
"id": 1,
"code": "BAZINGA",
"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
}
}
```
# Overview (/docs/api/feedback)
Feedback helps give your storefront more legitimacy by informing potential customers about your product quality and seller reputation. The better your feedback, the higher the likelihood visitors turn into customers.
On this page, we'll dive into the different feedback endpoints you can use to manage feedback programmatically. We'll look at how to query and reply to feedback.
## Endpoints [#endpoints]
* [List all feedback](/api/feedback/list-all-feedback)
* [Retrieve specific feedback](/api/feedback/retrieve-specific-feedback)
* [Reply to feedback](/api/feedback/reply-to-feedback)
## The feedback model [#the-feedback-model]
The feedback model contains all the information about your store's feedback, including the feedback's message, reply, and rating.
### Properties [#properties]
The unique identifier for the feedback.
The feedback sentiment, one of three:
* `POSITIVE`
* `NEUTRAL`
* `NEGATIVE`
The feedback rating, from one to five.
The time at which this feedback was deleted.
The time at which this feedback was first created.
The time at which this feedback was last updated.
The ID of the product this feedback belongs to.
The ID of the order this feedback belongs to.
The ID of the store this feedback belongs to.
Array of metadata related to the feedback; shows whether the feedback was imported.
The message the customer left in this feedback.
The reply to the feedback the storefront left.
Whether the feedback was automatic or not, one of two:
* `1`: Feedback is automatically left
* `0`: Feedback is not automatically left
***
# List all feedback (/docs/api/feedback/list-all-feedback)
This endpoint allows you to retrieve a paginated list of all your feedback received. By default, a maximum of fifteen feedback are shown per page.
## Endpoint
- Method: `GET`
- Path: `/v1/feedback`
- Full URL: `https://sell.app/api/v1/feedback`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
None.
## Query Parameters
- `limit` (`integer`, optional): Limit the number of blacklist rules returned.
- `page` (`integer`, optional): The page number you are attempting to access.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
Successful response.
#### 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": "null"
},
"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": {
"type": "null"
},
"message": {
"type": "string"
},
"reply": {
"type": "string"
},
"is_automatic": {
"type": "integer"
}
},
"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": "This product changed my life. My ex-wife wanted me back, my kids started talking to me, and my boss gave me a raise too!",
"reply": "The power of selling your soul to the Illuminati!",
"is_automatic": 1
}
],
"links": {},
"meta": {}
}
```
# Reply to feedback (/docs/api/feedback/reply-to-feedback)
This endpoint allows you to reply to a given feedback.
## Endpoint
- Method: `PATCH`
- Path: `/v1/feedback/{feedback}`
- Full URL: `https://sell.app/api/v1/feedback/{feedback}`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `feedback` (`integer`, required): The feedback path parameter.
## Query Parameters
None.
## Header Parameters
None.
## Request Body
- Required: Yes
### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"reply": {
"type": "string"
}
},
"required": [
"reply"
]
}
```
Example:
```json
{
"reply": "Do not sell your soul, kids!"
}
```
## Responses
### 200
Successful response.
#### 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": "null"
},
"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": {
"type": "null"
},
"message": {
"type": "string"
},
"reply": {
"type": "string"
},
"is_automatic": {
"type": "integer"
}
},
"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": "This product changed my life. My ex-wife wanted me back, my kids started talking to me, and my boss gave me a raise too!",
"reply": "Do not sell your soul, kids!",
"is_automatic": 1
}
}
```
# Retrieve specific feedback (/docs/api/feedback/retrieve-specific-feedback)
This endpoint allows you to retrieve a specific feedback by providing the unique identifier. Refer to [the list](/api/feedback#the-feedback-model) to see which properties are included with feedback objects.
## Endpoint
- Method: `GET`
- Path: `/v1/feedback/{feedback}`
- Full URL: `https://sell.app/api/v1/feedback/{feedback}`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `feedback` (`integer`, required): The feedback path parameter.
## Query Parameters
None.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
Successful response.
#### 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": "null"
},
"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": {
"type": "null"
},
"message": {
"type": "string"
},
"reply": {
"type": "string"
},
"is_automatic": {
"type": "integer"
}
},
"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": "This product changed my life. My ex-wife wanted me back, my kids started talking to me, and my boss gave me a raise too!",
"reply": "The power of selling your soul to the Illuminati!",
"is_automatic": 1
}
}
```
# Add products to group (/docs/api/groups/add-products-to-group)
This endpoint allows you to add products to an existing group. See the code examples for how to add products to an existing group with the SellApp API.
## Endpoint
- Method: `POST`
- Path: `/v2/groups/{group}/products/attach`
- Full URL: `https://sell.app/api/v2/groups/{group}/products/attach`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `group` (`integer`, required): The group path parameter.
## Query Parameters
None.
## Header Parameters
None.
## 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.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"attached": {
"type": "array",
"items": {
"type": "integer"
}
}
},
"required": [
"attached"
]
}
```
Example:
```json
{
"attached": [
1
]
}
```
# Create a group (/docs/api/groups/create-a-group)
This endpoint allows you to create a new group. See the code examples for how to create a new group with the SellApp API.
## Endpoint
- Method: `POST`
- Path: `/v2/groups`
- Full URL: `https://sell.app/api/v2/groups`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
None.
## Query Parameters
None.
## Header Parameters
None.
## 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"
]
}
```
### 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"
]
}
```
## Responses
### 200
Successful response.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"title": {
"type": "string"
},
"order": {
"type": "integer"
},
"image": {
"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": "null"
},
"section_order": {
"type": "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": "Rat race",
"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": 0,
"products": []
}
}
```
# Delete a group (/docs/api/groups/delete-a-group)
This endpoint allows you to delete a group.
This will permanently delete the group and its details.
## Endpoint
- Method: `DELETE`
- Path: `/v2/groups/{group}`
- Full URL: `https://sell.app/api/v2/groups/{group}`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `group` (`integer`, required): The group path parameter.
## Query Parameters
None.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
Successful response.
#### Content Type: `application/json`
Schema:
```json
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"title": {
"type": "string"
},
"order": {
"type": "integer"
},
"image": {
"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": "null"
},
"section_order": {
"type": "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": "Rat race",
"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": "This will make me rich!",
"description": "I am sure of it, Pinky."
}
]
}
}
```
# Overview (/docs/api/groups)
Groups are a way to help make your storefront navigable in SellApp — they are a collection of products you've grouped together in a tidy bunch.
On this page, we'll dive into the different group endpoints you can use to manage groups programmatically. We'll look at how to query, create, update, and delete groups, as well as how to add and remove products within groups.
## Endpoints [#endpoints]
* [List all groups](/api/groups/list-all-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 to group](/api/groups/add-products-to-group)
* [Remove products from group](/api/groups/remove-products-from-group)
* [List all products within group](/api/groups/list-all-products-within-group)
* [List specific product within group](/api/groups/list-specific-product-within-group)
## The group model [#the-group-model]
The group model contains all the information about your groups, including what products are in the group and the group's name, description, and image.
### Properties [#properties]
The unique identifier for the group.
The group title.
The order rank of the group.
The image belonging to the group.
Whether the group is unlisted or not. If set to true, the group will only be accessible via a direct link.
The time at which this group was first created.
The time at which this group was last updated.
The ID of the store this group belongs to.
The ID of the section this group belongs to.
The order rank of the group within the section it belongs to.
The amount of products linked to this group.
The products linked to this group, containing three types of info:
* `id`: The product ID
* `title`: The product title
* `description`: The product description
***
# List all groups (/docs/api/groups/list-all-groups)
This endpoint allows you to retrieve a paginated list of all your groups. By default, a maximum of fifteen groups are shown per page.
## Endpoint
- Method: `GET`
- Path: `/v2/groups`
- Full URL: `https://sell.app/api/v2/groups`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
None.
## Query Parameters
- `limit` (`integer`, optional): Limit the number of blacklist rules returned.
- `page` (`integer`, optional): The page number you are attempting to access.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
Successful response.
#### 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": {
"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": "null"
},
"section_order": {
"type": "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": "Rat race",
"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": "This will make me rich!",
"description": "I am sure of it, Pinky."
}
]
}
],
"links": {},
"meta": {}
}
```
# List all products within group (/docs/api/groups/list-all-products-within-group)
This endpoint allows you to retrieve a paginated list of all the products within your group. By default, a maximum of fifteen products are shown per page.
## Endpoint
- Method: `GET`
- Path: `/v2/groups/{group}/products`
- Full URL: `https://sell.app/api/v2/groups/{group}/products`
- Authentication: `Bearer` token required
## Code Samples
- Available languages: `curl`, `JavaScript`, `Go`, `Python`, `Java`, `C#`.
- PHP code samples are not generated for this API reference.
## Path Parameters
- `group` (`integer`, required): The group path parameter.
## Query Parameters
- `limit` (`integer`, optional): Limit the number of blacklist rules returned.
- `page` (`integer`, optional): The page number you are attempting to access.
## Header Parameters
None.
## Request Body
No request body.
## Responses
### 200
Successful response.
#### 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": "string"
}
},
"order": {
"type": "integer"
},
"visibility": {
"type": "string"
},
"delivery_text": {
"type": "null"
},
"additional_information": {
"type": "array",
"items": {
"type": "string"
}
},
"warranty": {
"type": "object",
"properties": {
"text": {
"type": "string"
},
"time": {
"type": "null"
},
"preferredUnit": {
"type": "string"
}
},
"required": [
"text",
"time",
"preferredUnit"
]
},
"other_settings": {
"type": "array",
"items": {
"type": "string"
}
},
"deleted_at": {
"type": "null"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"store_id": {
"type": "integer"
},
"category_id": {
"type": "null"
},
"section_id": {
"type": "null"
},
"section_order": {
"type": "null"
},
"is_discoverable": {
"type": "integer"
},
"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",
"warranty",
"other_settings",
"deleted_at",
"created_at",
"updated_at",
"store_id",
"category_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": "This will make me rich!",
"slug": "serial",
"description": "