Documentation
Set up FLIPR and connect it to your systems
How to get an account running, what each settings page controls, what every integration needs from you, and how to read and create returns through the API.
Getting started
- Create an account at getflipr.app/signup and verify your email address. Card plans start with a 14-day free trial. If you install FLIPR from the Shopify App Store instead, your account is created for you and billing goes through Shopify.
- Connect where your orders live. In Settings → Integrations, connect Shopify, Linnworks or another sales channel. FLIPR uses it to find a shopper's order when they start a return.
- Add a return address in Settings → Addresses. Labels are addressed to it.
- Connect a carrier in Settings → Integrations, then choose which services shoppers can pick in Settings → Carriers.
- Set your return rules in Settings → Return rules: the return window and which resolutions you offer.
- Brand the portal in Settings → Branding with your logo and colours.
- Share the portal. Copy your link from Settings → Portal link & domains and add it to your store and order emails.
To charge shoppers for return postage, also connect a payment provider (Stripe or Mollie). To send return emails from your own domain, connect an email provider (Resend or AWS SES).
Configuration
Everything is under Settings in the dashboard. Which pages you see depends on your role.
| Settings page | What it controls |
|---|---|
| Return rules | Return window and the resolutions shoppers can choose, such as refund or exchange. |
| Return reasons | The reasons a shopper picks from when returning an item. |
| Scrap rules | Which SKUs or warehouses are scrapped on receipt and not put back into stock. |
| Carriers | The carrier services offered in the portal and what shoppers pay for each. |
| Coupons | Codes that waive or reduce the return fee. |
| Exchange incentives | Bonus credit offered to shoppers who exchange. |
| Instant exchange | Sending the replacement before the return arrives. |
| Fraud prevention | Blocklist for shoppers who abuse returns. |
| The emails shoppers receive, and their templates. | |
| Portal link & domains | Your portal link, embedding it in your storefront, and your own returns domain. |
| Branding | Logo and colours shown in the portal. |
| Addresses | Return addresses used on labels, by country. |
| Team | Inviting staff and managing users. |
| Roles & permissions | What each role can see and do. |
| Plan & billing | Your plan, invoices and extra return packs. |
| Integrations | Sales channels, carriers, payments, email, storage, API keys and webhooks. |
Integrations
Open Settings → Integrations, pick the service and enter the details below. Integrations marked "Sign in" connect by authorising FLIPR in the other service, with nothing to copy.
Sales channels and order management
| Service | What you need |
|---|---|
| Shopify | Sign in. Install from the Shopify App Store, or connect your store domain from Integrations. |
| Linnworks | Sign in. Authorise FLIPR in Linnworks; it looks up orders and puts returned stock back. |
| Amazon SP-API | Client identifier, client secret, refresh token, Seller ID, region and primary marketplace ID. |
| eBay | Sign in with your eBay seller account. |
| TikTok Shop | Sign in with your TikTok Shop seller account. |
| WooCommerce | Store URL, consumer key and consumer secret. |
| Mirakl marketplaces | API key, marketplace and country. Covers Debenhams, Mountain Warehouse, Matalan, Kingfisher (B&Q / Screwfix), Secret Sales and Shop Simon, or any other Mirakl instance by URL. |
| Fruugo | Retailer Portal username and password. |
| Rackhams | Marketplacer API key. |
Carriers
When you connect a carrier, its return services are added to Settings → Carriers automatically, switched off. Set a price and switch on the ones you want; customers only see enabled carriers.
| Service | What you need |
|---|---|
| Royal Mail | API key. |
| Evri Corporate | Client ID and name, auth ID and secret, API key, and your production username and password. |
| DPD | Username, password and account number. |
| InPost | Client ID and client secret from the InPost developer portal, with the returns and tracking scopes, and your organization ID. Choose how customers send: a drop-off code they use at any InPost locker or InPost shop (no printer, the default) or a printed label. UK returns only. Connecting adds InPost to your UK carriers, switched off. Set a price and switch it on in Settings → Carriers. Use Test a return in the InPost panel to try it first. |
| Sendcloud | Public key and secret key. You can add more than one account, for example UK and EU. |
| Shippo | API key. |
| Ezi Returns | API token. |
Payments
| Service | What you need |
|---|---|
| Stripe | Secret key, publishable key and webhook signing secret. In Stripe, point the webhook at https://api.getflipr.app/api/stripe/portal-webhook. |
| Mollie | API key and profile ID. |
Email and storage
| Service | What you need |
|---|---|
| Resend | API key and your verified sending domain. |
| AWS SES | Access key, secret key, region and default from address. |
| AWS S3 | Access key, secret key, bucket name and region. |
Portal link and your own domain
Every account has a returns portal on getflipr.app. Your link, and the snippet for embedding the portal in your storefront, are in Settings → Portal link & domains.
To serve the portal from your own address, such as returns.yourbrand.com:
- With your DNS provider, add a
CNAMErecord for the subdomain pointing toportals.getflipr.app. - Enter the domain in Settings → Portal link & domains and connect it.
- Give the certificate a few minutes to be issued. After that the portal opens on your domain with your branding.
Connecting to the API
The FLIPR API lets your own systems, such as a helpdesk or warehouse tool, search and create returns, look up orders and read parcel tracking. It is JSON over HTTPS.
| Base URL | https://api.getflipr.app |
| Authentication | Authorization: Bearer flpr_live_… on every request |
| Request bodies | JSON, with Content-Type: application/json |
| Dates | UTC |
Create an API key
- Sign in as an admin and open Settings → Integrations.
- Choose API Access and add a key. Give it a label, such as "Helpdesk" or "Staging".
- Copy the key. It starts with
flpr_live_.
You can create one key per system and remove a key from the same page to revoke it.
A key cannot refund customers unless you set Allow refunds to Yes on that key. Leave it off for systems that only need to read or create returns.
Treat a key like a password. It gives full access to your account's data, so keep it on your server. Never put it in a web page, a mobile app or a public repository.
Check the connection
curl https://api.getflipr.app/api/v1/returns?limit=1 \
-H "Authorization: Bearer flpr_live_your_key"
A 200 with a returns array means the key works. GET /api/health needs no key and tells you the API is up.
Returns
A return is a parcel your team receives and processes. Its ID starts with FLP.
/api/v1/returnsSearch returns, newest first.
| Query | Description |
|---|---|
q | Matches customer name, email, order number, return ID, return tracking number or SKU. |
status | One status, or several separated by commas, for example received,completed. |
page | Page number, from 1. Default 1. |
limit | Results per page. Default 20, maximum 100. |
{
"returns": [
{
"id": "FLP-40318827",
"channel_order_id": "88201",
"customer_name": "Sam Carter",
"customer_email": "[email protected]",
"postcode": "M1 4AB",
"channel_source": "SHOPIFY",
"status": "received",
"return_tracking": "AB123456789GB",
"carrier": "Royal Mail",
"provider": null,
"created_at": "2026-10-01 09:14:22",
"completed_at": null,
"item_count": 1,
"items": [
{ "sku": "TS-BLK-M", "name": "Black T-shirt", "action": "refund", "exchangeSku": null, "qty": 1 }
],
"link": "https://getflipr.app/return/FLP-40318827"
}
],
"pagination": { "page": 1, "limit": 20, "total": 1, "pages": 1 }
}
/api/v1/returns/:idOne return with every field, its items, the latest 20 activity entries (action, detail, user, at) and, when the shopper started it in the portal, the linked returnRequest.
/api/v1/returnsCreate a return. It starts with the status received.
| Field | Description |
|---|---|
items | Required. Each item has sku, and optionally name, qty (default 1), price, size, color, action (default refund), and for exchanges exchangeNewSku, exchangeNewSize, exchangeNewTitle. |
orderNumber | The channel order number. Either this or customerName is required. |
customerName | Customer's name. |
customerEmail, postcode | Optional. |
channelSource, channelSubsource | Optional. Where the order was placed. |
linnworksOrderId | Optional. Needed if you will process the return in Linnworks. |
orderDate, notes | Optional. |
curl -X POST https://api.getflipr.app/api/v1/returns \
-H "Authorization: Bearer flpr_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"orderNumber": "88201",
"customerName": "Sam Carter",
"customerEmail": "[email protected]",
"items": [{ "sku": "TS-BLK-M", "name": "Black T-shirt", "qty": 1, "action": "refund" }]
}'
Responds 201:
{ "ok": true, "returnId": "FLP-40318827", "status": "received", "items": 1,
"link": "https://getflipr.app/return/FLP-40318827" }
/api/v1/returns/:idUpdate a return. Send only the fields you want to change: status, notes, returnTracking, carrier, provider, processedBy. Setting status to completed records the completion time.
{ "ok": true, "id": "FLP-40318827", "status": "completed" }
/api/v1/returns/:id/processBook the return in Linnworks: creates the RMA and puts the stock back, or scraps it where your scrap rules say so. The return must have a Linnworks order linked. Send no body to process every item, or { "items": [{ "sku", "action", "qty" }] } to process some.
The response lists processed, alreadyProcessed and errors by SKU. Calling it again is safe: items already booked are reported in alreadyProcessed and not booked twice.
/api/v1/returns/:id/refundSend the customer's money back for the items on the return marked refund. FLIPR refunds the same way the dashboard does: a Shopify order is refunded on Shopify and a WooCommerce order on WooCommerce, both to the original payment, and any other order through Linnworks, which passes the refund to the sales channel. The key must have Allow refunds turned on.
| Field | Description |
|---|---|
amount | Optional. The whole sum to refund, for a partial refund. Leave it out to refund what the customer paid for the items. It can never be more than that; a higher amount is refused with maxAmount in the response. |
includeShipping | Optional. true also refunds postage. Cannot be combined with amount. Not available for WooCommerce orders. |
shippingAmount | Postage to refund. Optional for Shopify orders, where it defaults to the postage paid; required for other orders when includeShipping is set. |
notify | Optional, Shopify orders only. false stops Shopify emailing the customer. Default true. |
allowAdditional | Optional. true to refund again on a return that has already been refunded. |
curl -X POST https://api.getflipr.app/api/v1/returns/FLP-40318827/refund \
-H "Authorization: Bearer flpr_live_your_key" \
-H "Content-Type: application/json" \
-d '{ "amount": 12.50 }'
{ "ok": true, "returnId": "FLP-40318827", "via": "shopify",
"amount": 12.5, "currency": "GBP", "refundId": "gid://shopify/Refund/…" }
The customer has been refunded only when the response is 200 with "ok": true. Anything else means no money moved, and error says why.
403: the key is not allowed to refund.409withalreadyRefunded: the return was refunded before. Nothing is refunded twice unless you sendallowAdditional. For a WooCommerce order it can also mean the items were already refunded on WooCommerce itself, whichallowAdditionaldoes not override.409withinProgress: another refund call for this return is still running. Wait, then read the return.422: Shopify, WooCommerce, Linnworks or the sales channel refused the refund.
If a call times out, read the return before trying again: refund_status is processed once a refund has gone through. When you create a return for a Shopify or WooCommerce order, pass the channel from the order search as channelSource so FLIPR knows where to refund it.
Orders
/api/v1/orders/search?q=Search your Linnworks orders by order number, email or reference. q is required, and Linnworks must be connected.
{
"orders": [
{
"linnworksOrderId": "3f2b…",
"orderNumber": "100234",
"channelOrderId": "88201",
"customerName": "Sam Carter",
"customerEmail": "[email protected]",
"postcode": "M1 4AB",
"channel": "SHOPIFY",
"status": "…",
"orderDate": "2026-09-20T10:02:00Z",
"tracking": "…",
"country": "United Kingdom",
"items": [{ "sku": "TS-BLK-M", "name": "Black T-shirt", "qty": 1, "price": 18, "rowId": "…" }]
}
]
}
/api/v1/orders/:linnworksOrderIdOne order with its lines, by the linnworksOrderId from the search. Use it to take a return against an order: it says what was paid for each line and how much of it is already back.
{
"linnworksOrderId": "3f2b…",
"orderNumber": 100234,
"channelOrderId": "88201",
"customerName": "Sam Carter",
"customerEmail": "[email protected]",
"channel": "shopify",
"channelSub": "My Store",
"status": "dispatched",
"orderDate": "2026-09-20T10:02:00Z",
"currency": "GBP",
"items": [
{ "rowId": "…", "sku": "TS-BLK-M", "name": "Black T-shirt", "qty": 2, "lineTotal": 32.4, "returnedQty": 1, "imageUrl": "https://…" }
]
}
lineTotalis what the customer paid for the whole line, VAT included, after discounts. Divide byqtyfor one unit.returnedQtyis how many units of the line are already booked back in Linnworks. Returns still on their way are not counted.statusisdispatchedoropen. An open order has not shipped, so it cannot be returned yet.imageUrlisnullwhen the product has no image.404: no order with that ID in your Linnworks.
Return requests
A return request is what a shopper submits in the portal, before the parcel arrives.
/api/v1/return-requestsSearch requests, newest first. q matches order number, customer name, email or request ID. limit defaults to 10, maximum 50.
Each entry in requests has id, order_number, customer_name, customer_email, status, return_action, return_reason, carrier, tracking_number, label_url, label_cost, created_at, updated_at and a link to it in the dashboard.
/api/v1/return-requests/:idOne request with every field, its items, and payment (amount, status, paid, paidAt) when the shopper paid for the label.
Tracking
/api/v1/tracking/:trackingNumberCarrier tracking events for a parcel, newest first. Results are cached for five minutes; add ?refresh=1 to fetch fresh data. The carrier is detected from the number; pass ?provider= if you already know it.
{
"trackingNumber": "AB123456789GB",
"provider": "royal_mail_api",
"carrier": "Royal Mail",
"latestStatus": "in_transit",
"latestStatusLabel": "🚚 In transit",
"events": [
{ "status": "in_transit", "statusLabel": "🚚 In transit", "description": "…",
"location": "…", "timestamp": "2026-10-02T08:30:00Z", "provider": "royal_mail_api" }
],
"cached": false,
"fetchedAt": "2026-10-02T09:00:00Z"
}
Errors
Errors come back as JSON with an error message:
{ "error": "Return not found" }
| Status | Meaning |
|---|---|
400 | The request is missing something or has nothing to change. The message says what. |
401 | The key is missing, wrong or has been removed. |
403 | The key is not allowed to do this, for example refund. |
409 | The return is already refunded, or a refund for it is in progress. |
404 | No return or request with that ID in your account. |
422 | A refund was refused by Shopify, WooCommerce, Linnworks or the sales channel. |
502 | Linnworks or the carrier failed. Safe to try again, except for a refund: read the return first. |
Inbound webhook
Some services push return updates to FLIPR. To receive them, add a Webhook in Settings → Integrations. FLIPR generates a URL of the form https://api.getflipr.app/api/ezi/webhook/<token>; paste it into the other service, such as Ezi Returns. The token in the URL identifies your account, so keep the URL private.
Support
Stuck on setup, or need something the API doesn't cover yet? Email [email protected]. If we need to look at your account, FLIPR support can open it in a time-limited, recorded session; we'll tell you when we do.