App guides
Restore orders finds orders that were deleted from your Swell store and restores them. Choose a period, review the orders deleted in it, and restore the ones you need with their original number and data.
The app reads the order.deleted events Swell records when an order is deleted, so it also finds orders deleted before you installed it. Restoring sends no emails, calls no webhooks and doesn't change your stock.
| When | What the app does |
| You open Orders > Restore orders | Checks your access to orders and shows the search form, set to the last 30 days with Only not canceled on. It doesn't search until you click Search. |
| You click Search | Reads the store's order.deleted events in the period, takes the latest deletion of each order, and lists the orders that don't exist now and have a customer account. |
| You click an order | Shows the order's full order.deleted event below the grid. |
| You click Restore and confirm | Recreates each selected order from its event, with its original ID and number. An order that exists again is skipped, and a failure on one order doesn't stop the others. |
| The restore finishes | Shows how many orders were restored, lists the ones that weren't with the reason, and searches the same period again. |
The app runs only when someone uses the page. It has no functions, doesn't react to orders being deleted, and stores no records of its own.
- An order can be found only through its order.deleted event. Swell records one when an order is deleted in the dashboard or through the API, unless the API request turns events off.
- An order can be found as long as its event exists. The app sets no limit on how far back you search, and events have no expiry date.
- The order must have a customer account. Orders without an account_id aren't listed.
- Test and live are separate environments, with their own orders and events. The app sees only the orders deleted in the environment it's opened in.
- Restoring needs Manage or Full access to orders. Staff with View access can search but not restore, and staff without access to orders can't use the page.
Install Restore orders from the Swell App Store.
The app has no settings.
Install it in the test environment
Installs are per environment. Install the app in your test environment first. Restore orders then shows under Orders in that environment's dashboard.
Delete a test order
Place a test order, or open one you no longer need. Choose Delete order, enter the order number, and confirm.
Find the order
Go to Orders > Restore orders and click Search. The form starts with the last 30 days, so the order is listed, with today under Date deleted. Click it to see its event data.
Restore the order
Select the order, click Restore 1, and click Restore 1 order to confirm. The page shows "Restored 1 order.", and the order leaves the list. Open Orders to check that it's back with its original number.
Go live
Install the app in the live environment. It finds the orders deleted in live, including orders deleted before you installed it. Orders and events don't carry over from the test environment.
What a user can do on the page depends on the Orders level of their role, set in Settings > Users under Manage roles:
| Orders level | What the user can do |
| Manage or Full | Search, see event data and restore orders. |
| View | Search and see event data. The page says they can't restore, and Restore doesn't show. |
| Restrict | Nothing. The page shows an error, and Search stays off. |
Users without a role have Full permissions or a list of permissions. With Full permissions or Orders in the list, they can search and restore. Without Orders, the page shows the same error as for Restrict. The app checks the user's access with Swell on every request, not only when the page opens.
To find deleted orders, go to Orders > Restore orders, set Date start and Date end, and click Search. The dates are when the orders were deleted, not when they were placed. Both days are included, in your browser's time zone. The form starts with the last 30 days, and you can search any period.
The search reads 1,000 events per request. In a long period with many deletions, the page shows its progress, such as "Searching · events page 2 of 5". The line above the grid shows the total, such as "186 deleted orders found".
| Column | Value |
| Order number | The order's number, or its ID if it has none. A Canceled badge marks orders that were canceled when they were deleted. |
| Date created | When the order was created. |
| Date deleted | When the order was deleted. |
| Grand total | The order's grand total in its currency. |
| Account ID | The ID of the customer's account. |
| Full name | The shipping name, or the billing name when that's empty. |
The grid shows 10 orders per page. Dates and amounts follow your browser's language and time zone.
These orders aren't listed:
- Orders that exist now, because they were restored or recreated with the same ID.
- Orders without a customer account.
- Older deletions of an order deleted more than once. The latest deletion in the period decides whether the order is listed, and the restore uses that event. If the latest deletion is left out, an older one isn't listed instead.
Only not canceled is on by default and leaves out orders that were canceled when they were deleted, such as orders deleted with Cancel and delete order. To list them too, turn it off and click Search. They show with a Canceled badge.
To sort the results, choose Date deleted or Date created under Sort by. Orders are sorted newest first, and the default is Date deleted. Sorting applies at once, without searching again, and returns to the first page. Orders without that date go last. Sort by shows when there are two or more results.
To see what an order held when it was deleted, click its row or its number. Event data opens below the grid with the full order.deleted event as JSON. The order is under data, with its items, addresses and totals. To hide it, click the order again or click Close.
The restore uses this data. Payments, shipments and other linked records are separate records, so they aren't in it.
To restore orders, select them with the checkboxes and click Restore. The button shows how many are selected, such as Restore 2, and the line above the grid shows "186 deleted orders found · 2 selected". The checkbox in the header selects the orders on the current page. Your selection stays when you change the page or the sort. To clear it, click Clear selection.
After you click Restore, the page asks you to confirm, such as "Restore 2 orders?", and says that each order is created again with its original ID, number and data, and that order emails and webhooks aren't sent. To start, click Restore 2 orders. To go back, click Cancel. A restore can't be undone from the app.
While the restore runs, the page shows its progress, such as "Restoring 10 of 25… Keep this page open until it finishes.", and the button shows Restoring…. The page sends 10 orders at a time, one group after another, so leaving the page stops the groups not sent yet. The page asks your browser to warn you before the tab is closed or reloaded, but going to another dashboard page doesn't warn you. Orders already restored stay restored and leave the list when you search again.
The result shows above the grid, such as "Restored 2 orders." If any weren't restored, it adds how many and lists each one with the reason, such as "Order 100551: The order already exists". The page then searches the same period again, so restored orders leave the list.
Select all shows the number of results, such as Select all 186, and selects every result on all pages, including pages you haven't opened. It shows until every result is selected. Check the period and Only not canceled before you click Restore.
The app writes the order back from its order.deleted event, with its original ID.
- Number and ID: the original order number and ID.
- Order data: the items, addresses, totals, status, dates and other stored fields, as they were when the order was deleted. Nothing is recalculated, so prices, discounts, taxes and shipping aren't applied again.
- Canceled orders: an order that was canceled when it was deleted comes back canceled.
- Payments and other records: payments, refunds, shipments, returns, invoices and credits are separate records, and deleting an order doesn't delete them. They point to the order's ID, so they show on the restored order again.
- Stock: doesn't change. Deleting an order doesn't return its items to stock, and restoring it doesn't take them again. If the order was canceled before it was deleted, canceling returned the stock, and restoring leaves it there.
- Customer: the customer gets no email, and the order shows on their account again. Deleting and restoring don't update the account's order count and order value. Swell updates them at the customer's next order, or when one of their orders is canceled or its total changes.
- Deleted customers: deleting a customer also deletes their orders, and these orders are listed here. Restoring one doesn't bring the customer back, so the order keeps an account_id that no longer exists.
- Events and notifications: the restore creates no order events, such as order.created, order.submitted or order.paid. No notification emails go out, webhooks aren't called, and functions that run on those events don't run. Apps and webhooks that reacted to the deletion aren't told about the restore, so they still treat the order as deleted.
- App hooks: functions with a before: or after: hook on order.created still run, because hooks run during the write itself. A before: hook that refuses the order makes its restore fail, with the hook's message.
- Sales: a deleted order that wasn't canceled stays counted in your store's sales, and the restore doesn't count it again.
- Subscriptions: on a subscription without a separate order schedule, deleting an order takes it out of the subscription's invoice and payment totals, and restoring it doesn't put it back. The totals are updated the next time an order of the subscription is created or its payments change.
- Channel: isn't restored. Only Swell can set an order's channel, so Channel on the order page shows a dash.
| Where | What it's for |
| Orders > Restore orders | The search form, the deleted orders, their event data, and Restore. |
| Orders | Restored orders, with their original number. |
| Apps > Restore orders | The app's page, where you uninstall it. |
| Developer > Console > Events | The store's events, including order.deleted. |
| Developer > Console > Logs | The app's calls to the Swell API, such as GET /events and POST /orders. |
- An order can be restored only from an order.deleted event. An order deleted through the API with events turned off can't be found.
- Orders without a customer account aren't listed, so they can't be restored.
- An order deleted more than once can be restored only from its latest deletion in the period.
- The app sets no limit on the period. A long period with many deletions takes several requests, at 1,000 events per request.
- A restore sends 10 orders per request. A selection has no size limit, and the page sends the requests one after another, so closing it stops the orders not sent yet.
- Restoring doesn't send notifications, create order events, call webhooks or change stock.
- Only the order is restored. A customer deleted with it isn't.
- An order's totals and status aren't recalculated, and Channel isn't restored.
- Data that other apps stored on the order comes back only for apps installed at the time of the restore.
- The app has no undo. To remove a restored order, delete it again.
The app shows its messages on the page. When a call to Swell fails during a search, Error details shows the call and Swell's response. The app writes no logs of its own. Its calls to the Swell API are under Developer > Console > Logs: choose the app under App to see them.
Check that the dates cover the day the order was deleted, not the day it was placed, and that you're in the environment it was deleted in. If the order was canceled, turn off Only not canceled. Orders that exist now and orders without a customer account aren't listed. To check for the event, look for order.deleted under Developer > Console > Events.
Search is off while the page checks your access, while a search or a restore is running, while you confirm a restore, when a date is empty, and when Date start is after Date end. For users without access to orders, it stays off.
Your role has Restrict for Orders, or you have no role and Orders isn't in your permissions. Ask the store owner for access to orders in Settings > Users, then reload the page.
Your role has View for Orders. You can search and see event data, but Restore doesn't show. To restore orders, you need Manage or Full. After your role changes, reload the page.
The request had no dashboard session. Sign in to the Swell dashboard and open Orders > Restore orders there.
The dashboard session has ended or belongs to another store. Sign in again and open the page from this store's dashboard.
The session cookie couldn't be read. Sign in to the dashboard again.
The request reached the app without the store's details from Swell. Open the page from Orders > Restore orders.
The app couldn't check the dashboard session or your access to orders with Swell. Try again in a minute. If it shows when the page opens, reload the page.
A search or restore request didn't come from the app's own page. Open the page from Orders > Restore orders and try again.
The event no longer exists, or it isn't an order.deleted event. Search again.
The order exists again, so it was skipped. Someone else may have restored it after your search. It leaves the list when the page searches again.
The event doesn't hold an order with a valid ID, so the order can't be restored from it.
Swell's answer had no order in it. Search again, and if the order is still listed, try again. The request shows as POST /orders in the logs.
The text after the order number is Swell's answer. If it's a message such as "… is sold out.", a before: hook of an installed app refused the order. If every order in a group of 10 shows the same message, the whole request failed. Select those orders and try again.
Swell answered a call with an error and no message. Try again in a minute. If it happens during a search, Error details shows the call and the response.
The app got an answer it couldn't read. Try again in a minute.
Restoring doesn't update the account's order count and order value. Swell updates them at the customer's next order, or when one of their orders is canceled or its total changes.
Channel isn't restored, so the order page shows a dash. The rest of the order isn't affected.
To uninstall the app, go to Apps > Restore orders and choose Uninstall app. This removes the app and its Restore orders entry under Orders. Uninstalling applies to the environment you are in, so remove the app from the test and live environments separately.
Restored orders stay, because they're regular orders. The app stores no records of its own, so nothing else is removed. order.deleted events stay too, so if you reinstall the app, it finds the orders you haven't restored.
| Route | What it does |
| GET /app-api/admin/access | Returns orders, the user's access to orders: full for Manage or Full, or view for View. Users without access get 403. |
| POST /app-api/admin/search | Takes date_from, date_to, not_canceled and page. Reads one page of 1,000 events and returns page, pages, count, results, order_ids and done. |
| GET /app-api/admin/event?id= | Returns the full order.deleted event. Other event types return 404. |
| POST /app-api/admin/restore | Takes event_ids, up to 10, and restores each order. Needs full access, and returns 403 for view. Returns results, each with event_id, order_id, number, a status of restored, skipped or failed, and an error unless restored. |
The app is an admin app with frontend.hosting: managed and no functions. Swell hosts the page and its Worker. The sidebar entry comes from content/restores.json, with nav parent orders and link frontend:///. models/restores.json is a placeholder collection for that view and stores no records. Other /app-api paths return 404, wrong methods return 405, and all other paths serve the built page.
The Worker doesn't read Swell-Context. Each route reads the _swell_admin_session cookie and calls GET /admin/api/session on Swell-Admin-Url with it as X-Session. The session must have a user_id, and its client_id must match Swell-Store-Id. It then calls GET /admin/api/user the same way, and a missing user returns 401. The user's access to orders comes from role.permissions.orders: restrict is none, view is view, and any other value is full. Without a role, all_permissions, no permissions list, or orders in permissions is full, and anything else is none. None returns 403 on every route, and restore returns 403 unless access is full. POST routes also need an Origin equal to the request's origin and a JSON Content-Type, and otherwise return 403.
Calls to Swell go to Swell-API-Host with Basic auth from Swell-Store-Id and Swell-Access-Token, the installation's key, which is per environment. permissions in swell.json is empty, which gives the key full Backend API access. The Worker calls only GET /events, GET /events/{id}, GET /orders and POST /orders. The key is removed from error details, and responses are Cache-Control: private, no-store.
Search reads GET /events with where[type]=order.deleted, $gte and $lt on where[date_created], sort=date_created desc, id desc, limit=1000 and the fields the grid needs. It keeps the first event of each data.id, drops events with no data.account_id and, with not_canceled, events with data.canceled: true, and checks the rest with GET /orders and where[id][$in], 100 IDs at a time. order_ids lists every order on the page, so the browser can skip older deletions on later pages. The browser asks for pages until done. date_from and date_to are the start of Date start and the start of the day after Date end, in the browser's time zone.
An order.deleted event holds the order record as it was stored, without linked records. Events have no TTL. The 90-day TTL in the events indexes applies to their webhook delivery records.
Restore reads GET /events/{id}, checks GET /orders for the order's ID, and calls POST /orders with the event's data plus $restore: true and $events: false. id, number, date_created and date_updated are stored as sent.
- $restore skips validation, including the unique check on number, formulas, model triggers, link writes and notifications. The triggers cover stock, taxes, promotions, and account and subscription updates.
- $events: false skips event capture, so no webhooks or asynchronous functions run and no activities are recorded.
- before: and after: hook functions aren't skipped. Those on order.created run, and so do those on declared order events whose conditions the write matches.
- The platform drops channel and attribution from the write, and stamp_channel doesn't run, so the order has neither.
- GET /events/{id} returns $app data only for installed apps, so data of an app uninstalled since the deletion isn't written back.
The Worker writes no logs. When a Swell API call fails during a search, the route returns { error, details } with status 502, and the page shows details under Error details. In a restore, each order's failure is in its result's error. The app's own messages, such as for invalid input, return only { error }. API calls made with the app's key are logged as requests, with the app's ID.
Swell builds and maintains the Restore orders app. For help with the app, email support@swell.is.