Skip to main content
Deep linking customers into the returns portal enables a frictionless returns experience. You only need two pieces of information to deep link: the order name (as used in Loop, often the customer-facing order number) and the store’s shop_domain (the hostname registered for that merchant, e.g. a *.myshopify.com domain for Shopify). Here’s how to get started.
If you are creating deep links for your own store and have access to your Loop admin, use the generate order link endpoint instead.

Become a Registered Third-Party App

Please submit the Loop Partner Registration form to become a registered third-party app in the Loop App Marketplace. Becoming a third-party app enables you to deep link customers into the returns portal. Once approved, Loop will provide a shared secret. Securely store this secret because you will use it to sign requests. Never allow this secret to be visible in the browser. To deep link the customer into the returns portal you need to redirect the browser to our deep link API. When successful, the deep link API redirects to the returns portal. The deep link API can be reached at GET https://api.loopreturns.com/api/v1/app/deep-link Required query parameters:
KeyDescription
orderOrder name (as used in Loop)
partnerYour registered partner name
shop_domainStore domain for the merchant, e.g. example.myshopify.com when the shop is on Shopify
hmacHMAC value used to verify authenticity of request
Use the shared secret to generate the HMAC digest, as described below. The HMAC should be added to the request’s query parameters. If the HMAC is verified and the other query parameters are valid then we will respond with a 307 Temporary Redirect that loads the returns portal for the order.

Generate the HMAC Digest for the Request

The HMAC used in the above API call should be generated using the following steps:
  1. Construct the query string with the keys sorted in alphabetical order. Example: order=1000&partner=your-company&shop_domain=example.myshopify.com
  2. Using the query string, generate a (lowercase) hex encoded HMAC using SHA-256.

HMAC Calculation Examples

const crypto = require('crypto');
const qs = require('qs');

const parameters = {
partner: "your-company", // Registered partner name
order: "1000", // Order name
shop_domain: "example.myshopify.com" // shop_domain
}

const alphabetizedQueryString = qs.stringify(parameters, { sort: ((a,b) => {
return a.localeCompare(b);
})});

const hmac = crypto.createHmac('sha256', 'your-partner-secret')
.update(alphabetizedQueryString.trim())
.digest('hex');

<?php
$parameters = [
    "partner" => "your-company", // Registered partner name
    "order" => "1000", // Order name
    "shop_domain" => "example.myshopify.com" // shop_domain
];

ksort($parameters);
$queryString = http_build_query($parameters);

$hmac = hash_hmac('sha256', trim($queryString), 'your-partner-secret');
echo $hmac;
?>
require 'openssl'
require 'uri'

parameters = {
  "partner" => "your-company", # Registered partner name
  "order" => "1000", # Order name
  "shop_domain" => "example.myshopify.com" # shop_domain
}

sorted_params = parameters.sort.to_h
query_string = URI.encode_www_form(sorted_params)

hmac = OpenSSL::HMAC.hexdigest('sha256', 'your-partner-secret', query_string.strip)
puts hmac
import hashlib
import hmac
import urllib.parse

parameters = {
    "partner": "your-company", # Registered partner name
    "order": "1000", # Order name
    "shop_domain": "example.myshopify.com" # shop_domain
}

# Sort parameters alphabetically and create query string
sorted_params = sorted(parameters.items())
query_string = urllib.parse.urlencode(sorted_params)

# Generate HMAC
secret = b"your-partner-secret"
hmac_hex = hmac.new(secret, query_string.strip().encode('utf-8'), hashlib.sha256).hexdigest()

print(hmac_hex)
import java.util.*;
import java.util.stream.Collectors;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

public class GenerateHMAC {
    public static void main(String[] args) throws Exception {
        Map<String, String> parameters = new TreeMap<>();
        parameters.put("partner", "your-company"); // Registered partner name
        parameters.put("order", "1000"); // Order name
        parameters.put("shop_domain", "example.myshopify.com"); // shop_domain

        String queryString = parameters.entrySet()
                                        .stream()
                                        .map(entry -> entry.getKey() + "=" + entry.getValue())
                                        .collect(Collectors.joining("&"));

        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKeySpec = new SecretKeySpec("your-partner-secret".getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        mac.init(secretKeySpec);

        byte[] hash = mac.doFinal(queryString.trim().getBytes(StandardCharsets.UTF_8));
        StringBuilder hmacHex = new StringBuilder();
        for (byte b : hash) {
            hmacHex.append(String.format("%02x", b));
        }

        System.out.println(hmacHex.toString());
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

class Program
{
    static void Main()
    {
        var parameters = new SortedDictionary<string, string>
        {
            { "partner", "your-company" },
            { "order", "1000" },
            { "shop_domain", "example.myshopify.com" }
        };

        var queryString = string.Join("&", parameters.Select(kv => $"{kv.Key}={kv.Value}"));

        using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes("your-partner-secret")))
        {
            var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(queryString.Trim()));
            string hmacHex = BitConverter.ToString(hash).Replace("-", "").ToLower();
            Console.WriteLine(hmacHex);
        }
    }
}
package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"net/url"
	"sort"
)

func main() {
	parameters := map[string]string{
		"partner":     "your-company", // Registered partner name
		"order":       "1000",         // Order name
		"shop_domain": "example.myshopify.com", // shop_domain
	}

	// Sort the parameters by key
	keys := make([]string, 0, len(parameters))
	for k := range parameters {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	queryString := ""
	for i, key := range keys {
		queryString += key + "=" + url.QueryEscape(parameters[key])
		if i < len(keys)-1 {
			queryString += "&"
		}
	}

	// Generate HMAC
	secret := []byte("your-partner-secret")
	mac := hmac.New(sha256.New, secret)
	mac.Write([]byte(queryString))
	hmacHex := hex.EncodeToString(mac.Sum(nil))

	fmt.Println(hmacHex)
}