APIWebhooksSDK
Email Templates
- New: seven routes in Email Templates for Email Templates: the emails a store can write listed, one read with its original HTML, its variables and parts, changed, previewed for a sample buyer and put back as Shoply wrote it, and the CSS every email gets read and changed. They need two new permissions,
emails.readandemails.write. - New: Get an email template answers
originalSubjectSource, the original subject written with its variables (Your {{ store.name }} order is delivered ({{ order.id }})), besideoriginalSubject, which is the same for a sample buyer. - Changed: the subjects set by
firstSubject,declinedSubjectandsecondSubjectin Change Cart Recovery, andfirstSubjectandsecondSubjectin Change Win-Back, are the subjects Email Templates shows for those emails, and may hold their variables, such as{{ store.name }}.
Support Tickets
- New: seven routes in Support Tickets for Support Tickets: the store’s tickets listed with four figures, one read with its conversation, a reply, resolve and reopen, the feature switched on or off, and a ticket’s picture. They need two new permissions,
tickets.readandtickets.write. - New: five routes in the Customer API for the buyer’s half: their tickets listed with the orders they can ask about, a ticket opened, read, written on and resolved.
- New: four webhook events:
ticket.opened,ticket.message,ticket.resolvedandticket.reopened. An endpoint that takes every event gets them. See Webhook events. - New:
emailTicketsEnabledanddiscordTicketsEnabledin Get email and alert settings. - New: @shoplygg/node 0.4.0, shoplygg/shoply-php 0.4.0 and shoply 0.4.0 have the new routes and events, and October 21’s too: 0.3.0 was never published.
- New:
htmlon each message of a ticket’sconversation, in Get a support ticket and the Customer API’s, and onticket.message’s message: itsbodyas Markdown draws it, escaped and safe to show as it is. Links go only to the web or an email address and open in a new tab; one whose words are not its address names its host after it; a picture written in Markdown is a link and never loaded.bodyis still the words as written.
Coupons for one tag
- New:
customerTagin Create a coupon and Update a coupon: empty for anybody with the code,vip, or the ID of one of the store’s tags. A buyer whose email does not wear it is refused the code at checkout and at Pay. Left out of an update, the coupon keeps its own. See A coupon for one tag. - New:
customerTagon each coupon the API answers: null, or the tag with its name and colour, andlivefalse where nobody can wear it now (VIP switched off, or a tag since deleted). - New:
couponson each of the store’s tags in List customer tags: how many coupons are only for it.
Saving the store’s settings
- New:
settingsVersionin Get the store, andexpectedVersiontaken by Update the store. It moves only when something that route saves changes, whereupdatedAtmoves for every other setting of the store too: Support Tickets switched on, its tax, its payment options. Sent, a save is refused withstale_writeonly for a real change in between. - New:
versionin Get email and alert settings, the same for those settings. - Fixed: a coupon’s
updatedAtno longer moves each time a buyer uses one, so Update a coupon sent withexpectedUpdatedAtis no longer refused for a sale in between.
The Checkout Kit
- Changed: kit.js 1.4. Where a product asks the buyer questions (custom fields), the
paymentpiece asks them on a page of their own, with Continue to Payment in thepaypiece, and then shows the payment methods with the answers on one line and Edit. Theemailandbillingpieces are empty until then, and thesummarypiece no longer holds the questions. The line of answers has the class.shoply-kit-answers.
The customer panel’s downloads
- New:
downloads.ordersin Get the signed-in buyer: the buyer’s paid orders newest first, each with what it bought, its own files and its own instructions, as the customer panel’s Downloads & Setup page now shows them.downloads.filesanddownloads.instructions, every order’s together, are answered as before. - New: @shoplygg/node 0.4.1, shoplygg/shoply-php 0.4.1 and shoply 0.4.1 type
downloads.orders, andhtmlon a ticket’s messages.
Order IDs
- Changed: a new order’s ID is no longer a UUID. It reads
a2855h0p1y4-71329ed4d95-1000427, 31 characters, and ends in a number that counts every order on Shoply. Orders made before keep their UUIDs, and every route and webhook answers either. Code that checks an order’s ID is a UUID has to stop: treat it as text of up to 36 characters. See IDs. - Changed: an order is named by its whole ID wherever it was named by the first eight characters: on its invoice PDF and the file’s name, in a dispute’s evidence, in
{order}for a custom payment method, and inlabelon the orders a buyer’s support ticket can be about. - Fixed: shoply.js 1.26.1 empties the basket after a payment whose order has an ID of the new shape. 1.26.0 kept only a UUID as the checkout it remembered.
APIWebhooksSDK
Email Marketing and customer tags
- New: nine routes in Email Marketing: Win-Back’s settings and figures, the buyers it writes to and one buyer, the subscribers’ figures, asking at checkout switched on or off, and the subscribers listed, exported and unsubscribed. They need two new permissions,
marketing.readandmarketing.write. - New: eight routes in Customers for tags: the store’s own listed, added, changed and deleted, VIP and Disputed Before changed, and a customer’s tags set, one put on and one taken off. Changing them needs a new permission,
customers.tags; listing them iscustomers.read. - New:
tagson a customer, in List customers, Get a customer and everycustomer.webhook. List customers and Export customers taketag, andonlytakessubscribed. The export has two more columns at its end, Tags and Subscribed. - New: six webhook events:
customer.tagged,customer.untagged,winback.email_sent,winback.won_back,subscriber.subscribedandsubscriber.unsubscribed. An endpoint that takes every event gets them. See Webhook events. - New:
marketing_consentandwon_backamong the kinds in an order’stimeline. - Changed: a buyer who unsubscribes from a Win-Back email, or whom the store takes off its subscribers, gets no Cart Recovery emails either, and
cart.unsubscribedandsubscriber.unsubscribedare both sent for a Cart Recovery unsubscribe of a subscriber. - New: kit.js 1.3. The box asking for leave to email the buyer has the class
.shoply-kit-consent. - New: the SDKs have the new routes from 0.4.0 (0.3.0, which was to carry them, was never published).
Apps and OAuth
- New: apps that any seller connects to their store by OAuth’s authorization code flow, with PKCE. A seller approves an app on Shoply’s approval page, and the app’s server swaps the code at
POST /v1/oauth/tokenfor a token,shoply_at_..., which is a key of that store with the permissions approved. It works until the seller disconnects the app.POST /v1/oauth/revokegives one up. - New:
appin Get the current key, the app a token is for, or null for the store’s own keys. - New: two webhook events,
app.connectedandapp.disconnected. An endpoint that takes every event gets them. See Webhook events. - Changed: a webhook endpoint made with an app’s token is deleted when the app is disconnected. One made with the store’s own key, or in the dashboard, is not.
- New: @shoplygg/node 0.2.0, shoplygg/shoply-php 0.2.0 and shoply 0.2.0 take an app’s token as their key, and have
oauthto get one: the approval address, a PKCE pair, the code swapped, a token given up.
Server SDKs
-
New: shoply 0.1.0 on PyPI, the API for your own server in Python 3.9 or later, as the Node.js and PHP packages are: every route as a method named after it, its fields as keyword arguments,
TypedDictanswers for mypy and your editor, retries with anIdempotency-Key, lists a page at a time or all withfor,shoply.webhooks.verify, andshoply.Customerfor the Customer API. Each route’s page shows its call in Python too. -
New: shoplygg/shoply-php 0.1.0, the API for your own server in PHP 8.1 or later, as the Node.js package is: every route as a method named after it, array shapes for PhpStorm and PHPStan, retries with an
Idempotency-Key, lists a page at a time or all withforeach,Shoply\Webhooks::verify, andShoply\Customerfor the Customer API. Each route’s page shows its call in PHP too. -
Fixed: @shoplygg/node 0.1.1 sends
kindwith Add a file to a dispute’s answer. 0.1.0 left it out, so every file went asotherand took the place of the one before. - Changed: @shoplygg/node 0.1.1 names its source, github.com/shoplygg/shoply-node, where issues can be filed.
-
New: @shoplygg/node 0.1.0, the API for your own server: every route as a typed method named after it, retries with an
Idempotency-Keyso a change is never made twice, lists a page at a time or all withfor await,webhooks.verifyfor a delivery’s signature, andShoplyCustomerfor the Customer API. Each route’s page shows its call.
Customer API
- New: the Customer API, 18 routes for a buyer’s own browser or app. A buyer signs in with a code emailed to them (Send a sign-in code, Sign in with the code) and gets a token,
shoply_ct_..., for their own orders and keys, subscriptions and affiliate page at one store. No API key reaches these routes, and a buyer’s token reaches no other.
Disputes
- Changed: Submit a dispute’s answer and Accept a dispute work for Revolut, Adyen, and PayPal connected with API keys, as well as Stripe:
answeredFromisherefor those. Two new codes:provider_key(502) where the provider will not let the store’s key or app answer disputes, andfile_not_taken(409) for a file the provider does not take (Adyen takes no PNG, and a PDF of up to 2 MB). See Disputes. - Changed: an Adyen chargeback that Adyen says can still be defended is
needs_response, notlost, until Adyen says it was lost or its defense period ends. - New: 16 routes in Disputes: list and read a store’s disputes with what Shoply recorded about each order, save an answer, submit or accept a Stripe dispute, mark one as answered in its provider’s own dashboard, add files, get the answer as a PDF, hide what a disputed order delivered, and the dispute settings.
- New: two permissions for them,
disputes.readanddisputes.write. A key made before today has neither. - New: five webhook events:
dispute.opened,dispute.updated,dispute.won,dispute.lostanddispute.closed. An endpoint that takes every event gets them. See Webhook events. - New:
disputeson an order in Get an order, its disputes newest first, anddispute_answeredamong the kinds in itstimeline. - New:
emailDisputeOpenedEnabled,emailDisputeClosedEnabledanddiscordDisputesEnabledin Get email and alert settings. They are the same three switches asemailOpened,emailClosedanddiscordin the dispute settings, which answer as before.
More of the dashboard through a key
- New: four routes in Cart Recovery: its settings and figures, the carts and one cart. They need two new permissions,
recovery.readandrecovery.write. - New: eleven routes in Payment Routing, all of what its part of the dashboard does. They need two new permissions,
routing.readandrouting.write. - New: eight routes in Custom payment methods, under
payments.readandpayments.write. - New: Approve a payment to check, Reject a payment to check and Get an order’s proof of payment, under
orders.fulfil. - New: Set how long an unpaid order is kept, for the store and for one payment method, under
payments.write. - Changed:
payments.read,payments.writeandorders.fulfilreach those routes, so a key that has one of them reaches its routes from today. - Fixed: Switch paying with balance on or off answered the switch as it was before the change.
Webhook events
- New:
order.payment_submitted,order.rerouted,review.removed,review.flag_declined,affiliate.balance_changed,cart.email_sent,cart.recovered,cart.unsubscribed,routing.processor_paused,routing.processor_resumedandfraud.checkout_blocked. An endpoint that takes every event gets them. Webhook events now says whatdatais for each group of events. - New: a cart has
emailedAt,secondEmailAt,couponCode,recoveredOrderIdandrecoveredAt.
APIWebhooksSDKPayments
Subscriptions
- New: 13 routes in Subscriptions. List and read subscriptions, their settings and the options sold by subscription, and cancel, undo a cancellation, pause, resume, add free days or email the renewal again.
- New: two permissions for them,
subscriptions.readandsubscriptions.write. A key made before today has neither. Give it them with Edit Key in Developers, API Keys. - New: seven webhook events:
subscription.started,subscription.renewed,subscription.cancelled,subscription.ended,subscription.paused,subscription.resumedandsubscription.charge_failed. See Webhook events. - New:
subscriptionIdon an order, andrunningSubscriptionson a product, the number of running subscriptions that deleting it would end. - New: shoply.js 1.26.0. Every variant in the catalogue has
renews({ every, unit }, or null for one sold once), andrenews(variant)reads it. - New:
@shoplygg/jsand@shoplygg/react0.1.1, withrenewsin their types.
Other changes
- New:
totals.recoveredin Get the overview: the orders and revenue Cart Recovery brought back. - New:
meta.routing.providersin List payment methods: the payment methods Payment Routing is choosing between. - New:
autoReviewsin Get email and alert settings. - Removed:
couponTintfrom the email settings. It was added on October 13.
APISDK
- New: eight routes in Storefront code. Read a storefront’s files, add, save, rename and delete one, give a storefront files of its own, and publish them. They use
storefronts.readandstorefronts.write, which keys already had. - New: the Shoply CLI,
@shoplygg/cli, and the npm packages@shoplygg/jsand@shoplygg/react, all at 0.1.0. - New: custom payment methods. An order paid with one has its ID in
gateway(custom_and 16 hex characters) and hascustomPayment, which says what the buyer was told and what they sent. - New:
meta.orderin List payment methods: connected and custom methods in the one order the checkout shows them. - New:
emailCustomPaidEnabledanddiscordCustomPaidEnabledin the email settings.
APIPayments
- New: custom fields. A variant has
customFieldsandcustomFieldsOn, which the product routes read and write. An order hascustomFields, the buyer’s answers. - New: payment providers
shopify,skrill,pandabase,tagada,rewarble,adyen,mercadopagoandmonei, as values of an order’sgateway. - New:
authorizeUrlandcopieson a payment method: where to send the seller to connect it, and what to copy into the provider’s own dashboard.
APISDKPayments
- New:
requestson an order: every webhook delivery and dynamic delivery Shoply sent your servers about it, newest first. - New:
deliveryInstructionson a product, sent with whatever variant was bought. The create, update and bulk update routes take it. - New:
unpaidHourson each payment method, andmeta.unpaidwith the store’s own time and its limits: how long an unpaid order is kept before it is cancelled. - New: Export blacklist rules and Export fraud events, under
fraud.read. - New:
checkson the store’s domain: whether it points at Shoply, is proved yours, and is secure. - New: payment providers
skinloop,square,revolut,lemonsqueezyandamazonpaymentservices. A payment method’s field can havemax, its own length limit. - New: kit.js 1.2. A cart line takes
addonsandoffer, andkit.set()changes them. - Changed: Send an order’s email again is limited to five times an hour for one customer, across all their orders. It was five an hour for each order.
- Changed: an upsell’s
hideOwnedis false unless you send it. It was true.
APISDK
- New: seven routes in Upsells, with two permissions,
upsells.readandupsells.write. An order line hasaddonOfandupsellId. - New: shoply.js 1.25.0:
addons,together,setAddons,cartOffers,takeOfferandoffersSeen. - New:
blacklistedByon a customer, every rule that refuses them. Clear a customer from the blacklist takesaddresses. - Fixed: a category’s
productsare in the store’s own order. They came in no set order.
API
- New: Export customers.
- Changed: Export orders takes
rows,ordersorlines, and has every field an order’s page shows after its first thirteen columns, which are as they were. - New: both exports take
check=1, which answers how many rows there are without sending the file. A file can be any length. Exports count toward 30 every 10 minutes a store. - Changed: a sale in Finance is what the buyer paid. Get profit has
commission, affiliate commission counted as a cost. Get profit, Get the books and Export the books count toward 20 every 10 minutes a store, shared with the dashboard’s Generate Report.
APIWebhooksPayments
- Changed: an endpoint that keeps refusing deliveries is held. From the second refusal in a row nothing more is sent to it until the hold ends, and then one delivery is tried. Up to 5,000 deliveries wait for one endpoint. See Webhooks.
- New: payment providers
whop,cryptomus,heleket,oxapay,nmi,mollieandsumup. A payment method’s switches havegroupandneeds. - Removed:
emailTintfrom the email settings.emailAccentis in its place.
API
- New: three routes that act for an affiliate: Ask for a payout for an affiliate, Take back a payout request and Move commission to store balance. The last needs
customers.balanceas well asaffiliates.payouts. See A panel of your own. - New: Create a payment link and Delete a payment link. List invoices takes
kind, and answerskind,usesandlinkOf. Send an invoice takesemail. - Fixed: Send an invoice failed for every invoice.
- New: a variant can sell down from a number you set:
stockMode3, withstock. - New:
flagon a review in List reviews: whether the store flagged it for removal, and the answer. - New: Deliver an order again is limited to 10 an hour for one order, and Retry a dynamic delivery to 150 every 10 minutes a store.
APIWebhooks
- New: the API, at
https://api.shoply.gg/v1, behind a secret key for each store. 188 routes, 43 permissions, and a key can be held to addresses and domains of your own. See the introduction. - New: webhooks, 21 events, signed with
X-Shoply-Signature. See Webhooks.

