Membership Contracts
Send customer portal magic link via email
Automatically generates and emails a secure magic link to the customer for accessing their membership management portal. This is a convenience endpoint that combines token generation and email delivery in a single API call.
Key Features:
- Automated Delivery: Generates magic link and sends email in one operation
- Customer Lookup: Finds customer by email address automatically
- Branded Emails: Uses shop’s configured email templates and branding
- Membership Validation: Only sends if customer has active memberships
- Time-Limited Links: Email contains token that expires after configured duration
Email Contents: The sent email typically includes:
- Magic Link Button: One-click access to customer portal
- Link URL: Full URL with embedded authentication token
- Expiration Notice: When the link will expire (e.g., “Valid for 24 hours”)
- Shop Branding: Store logo, colors, and custom messaging
- Help Text: Instructions on how to use the portal
Workflow:
- API receives customer email address
- System looks up customer in Shopify by email
- Validates customer has active membership contracts
- Generates secure JWT authentication token
- Constructs magic link URL with token
- Sends branded email with magic link to customer
- Returns success confirmation to API caller
Email Template Customization: Email appearance and content can be customized via:
- Shop’s email notification settings in admin
- Custom email templates for magic links
- Localization settings for customer’s language
- Custom branding (logo, colors, footer)
Common Use Cases:
- Customer support: send portal access link to customers over phone/chat
- Automated workflows: trigger magic link emails based on events
- Forgot password alternative: passwordless portal access
- Post-purchase flows: send portal access after first order
- Reactivation campaigns: re-engage paused/cancelled customers
- Customer onboarding: welcome emails with portal access
- Membership reminders: include portal link in reminder emails
Integration Example:
GET /api/external/v2/subscription-contracts-email-magic-link?
email=customer@example.com&
api_key=your_api_key
This sends a magic link email to customer@example.com for portal access.
Error Handling:
- If customer not found, returns 400 Bad Request
- If customer has no active memberships, returns 400
- If email service fails, returns 500 Internal Server Error
- Invalid email format returns 400 Bad Request
Email Delivery Notes:
- Emails are sent asynchronously (may take 1-5 minutes to deliver)
- Check spam folders if customer doesn’t receive email
- Respect customer’s email preferences and unsubscribe status
- Rate limits may apply to prevent abuse
Security Considerations:
- Only send to verified customer email addresses
- Email contains passwordless authentication link
- Links expire after configured duration (default: 24-72 hours)
- Sending to wrong email grants that person membership access
- Consider email verification before using this endpoint
Authentication: Requires API key authentication via X-API-Key header or api_key parameter
GET
/
api
/
external
/
v2
/
subscription-contracts-email-magic-link
Send customer portal magic link via email
curl --request GET \
--url https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-linkimport requests
url = "https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-link"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-link', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const url = 'https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-link';
const options = {method: 'GET'};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-link",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-link"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}require 'uri'
require 'net/http'
url = URI("https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-link")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body<string>"<string>""<string>""<string>"⌘I
Send customer portal magic link via email
curl --request GET \
--url https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-linkimport requests
url = "https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-link"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-link', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const url = 'https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-link';
const options = {method: 'GET'};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-link",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-link"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}require 'uri'
require 'net/http'
url = URI("https://membership-admin.appstle.com/api/external/v2/subscription-contracts-email-magic-link")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body<string>"<string>""<string>""<string>"