Security and data
What we read, what we keep, and what we do not
A returns app sees customer names, addresses and order history. The least interesting thing we can do with that is the correct thing.
What we read from Shopify
Orders, so the portal can show a customer what they actually bought and check it is still returnable. Products and variants, so an exchange can offer real replacements at real prices. Customer details attached to those orders, so a request can be matched to the right person.
Permission to create and process returns is a separate, optional grant. It is requested only when a merchant wants to process returns through the app, and it is checked against Shopify before every single write rather than remembered — so revoking it takes effect immediately rather than whenever a cache expires.
What we store
The request itself: which items, how many, the reason, any note, and the photos the customer attached. Contact details from the order so the request can be found and answered. A snapshot of the item as it was at the time — title, variant and price — so a catalogue change next month does not rewrite what somebody asked for.
We also keep a record of every write we made to Shopify: what was attempted, when, and what came back. That ledger is what makes it possible to answer “was this refunded?” with evidence rather than an assumption, and it is the reason a failed call is never blindly repeated.
We do not store card numbers, bank details or payment credentials. Swapify+ never sees them; refunds are processed by Shopify against the original payment.
Keeping merchants apart
Every query the application makes is scoped to a single merchant by the code path that issues it, and the database enforces the same boundary independently through row-level security and composite foreign keys. A request, a photo and a notification each belong to exactly one merchant, and cannot be attached to another one even by a hand-written statement.
Identifiers from another store are refused rather than looked up. Asking for an order that belongs to a different merchant returns the same “not found” as asking for one that does not exist, because confirming that something exists somewhere on the platform is itself a disclosure.
Deletion, and what Shopify asks us
Shopify forwards privacy requests to apps on a customer's or a merchant's behalf, and Swapify+ acts on them: a request for a customer's data, a request to erase a customer, and a request to erase an entire shop after uninstall. Erasing a customer removes their requests and the photos attached to them from storage as well as from the database.
Uninstalling ends our access immediately — the credentials stop working because Shopify stops honouring them, not because we choose to stop using them.
Reporting something
If you have found a security problem, tell us before you tell anyone else, and please test against a development store rather than a real merchant's data. We will provide one.