Softlogin Store Credits API
Apply store credits at checkout without full Shopify login. Supports standard storefronts and headless commerce.
Apply store credits to customer carts from custom storefronts or headless checkouts. This API enables credit redemption without requiring full Shopify login.
Overview
The Softlogin API allows customers to apply store credits during checkout. It supports both standard Shopify storefronts and headless commerce setups.
Deployment Types
| Type | API Base URL |
|---|---|
| Standard Storefront | https://your-store.myshopify.com/apps/subscribfy-api/softlogin |
| Headless Commerce | https://checkout.your-domain.com/apps/subscribfy-api/softlogin |
Authentication
The Softlogin API uses session-based authentication. Customers must be logged into Shopify (verified via cookies) for requests to succeed.
Available Actions
| Action | Description |
|---|---|
customer-check | Verify customer and retrieve balance/subscription status |
discount | Apply or remove store credits from cart |
Customer Check
Verify customer identity and retrieve their store credit balance and subscription status.
Request
POST /apps/subscribfy-api/softlogin?action=customer-check&t={timestamp}Parameters:
Prop
Type
Response
{
"customer_email": "john@example.com",
"customer_phone_private": "***-***-4567",
"shopify_customer_id": "7211677024514",
"current_balance": 50.0,
"subscription_status": "ACTIVE",
"membership_status": 1,
"credits_method": "functions",
"currency_code": "USD"
}Response Fields
Prop
Type
Apply Store Credits
Apply store credits to the current cart. The cart token must be fetched fresh before each request.
Request
POST /apps/subscribfy-api/softlogin?action=discount&cid={customer_id}&exm={membership_flag}&token={cart_token}&st={amount}&t={timestamp}Parameters:
Prop
Type
Response
{
"sac": 25.0,
"sch": "abc123xyz",
"cdi": 12345
}Response Fields
Prop
Type
After Successful Response
Update cart attributes with the store credit information:
POST /cart/update.js
{
"attributes[subscribfy_checkout_storecredits_label]": "Store Credits",
"attributes[subscribfy_checkout_storecredits_value]": {sac},
"attributes[subscribfy_checkout_storecredits_hash]": {sch}
}Remove Store Credits
Remove previously applied store credits from the cart.
Step 1: Clear Cart Attributes
POST /cart/update.js
{
"attributes[subscribfy_checkout_storecredits_label]": "",
"attributes[subscribfy_checkout_storecredits_value]": "",
"attributes[subscribfy_checkout_storecredits_hash]": "",
"attributes[subscribfy_store_credits_code]": "",
"attributes[subscribfy_store_credits]": "",
"attributes[subscribfy_store_credits_id]": ""
}Step 2: Notify API
POST /apps/subscribfy-api/softlogin?action=discount&cid={customer_id}&exm=1&cp={pathname}&t={timestamp}JavaScript Implementation
Complete Example
// Configuration
const SUBSCRIBFY = {
apiPrefix: 'https://your-store.myshopify.com/apps/subscribfy-api',
customerEmail: null,
customerId: null,
membershipStatus: 0,
balance: 0,
cart: null,
cartToken: null
};
// API Helper
const subscribfyApi = {
async post(url, data = {}) {
const response = await fetch(url, {
method: 'POST',
body: new URLSearchParams(data),
credentials: 'include',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
}
});
return response.json();
},
async getCart() {
const response = await fetch('/cart.js');
SUBSCRIBFY.cart = await response.json();
SUBSCRIBFY.cartToken = SUBSCRIBFY.cart.token;
return SUBSCRIBFY.cart;
},
flattenObject(obj, prefix = '') {
const result = {};
for (const [key, value] of Object.entries(obj)) {
const newKey = prefix ? `${prefix}[${key}]` : key;
if (typeof value === 'object' && value !== null) {
Object.assign(result, this.flattenObject(value, newKey));
} else {
result[newKey] = value;
}
}
return result;
}
};
// Check customer and get balance
async function checkCustomer(email) {
const response = await subscribfyApi.post(
`${SUBSCRIBFY.apiPrefix}/softlogin?action=customer-check&t=${Date.now()}`,
{
customer_email: email,
location_origin: window.location.origin,
location_pathname: window.location.pathname,
location_search: window.location.search
}
);
if (response.status_code) {
throw new Error('Customer not found');
}
SUBSCRIBFY.customerEmail = response.customer_email;
SUBSCRIBFY.customerId = response.shopify_customer_id;
SUBSCRIBFY.balance = response.current_balance;
SUBSCRIBFY.membershipStatus = response.membership_status;
return response;
}
// Apply store credits
async function applyStoreCredits(amount) {
await subscribfyApi.getCart();
const exm = SUBSCRIBFY.membershipStatus ? 3 : 2;
const cartFlat = subscribfyApi.flattenObject(SUBSCRIBFY.cart, 'cart');
const data = {
customer_email: SUBSCRIBFY.customerEmail,
customer_id: SUBSCRIBFY.customerId,
email: SUBSCRIBFY.customerEmail,
cid: SUBSCRIBFY.customerId,
exm: exm,
token: SUBSCRIBFY.cartToken,
st: amount,
location_origin: window.location.origin,
location_pathname: window.location.pathname,
location_search: window.location.search,
...cartFlat
};
const url = `${SUBSCRIBFY.apiPrefix}/softlogin?action=discount&cid=${SUBSCRIBFY.customerId}&exm=${exm}&token=${encodeURIComponent(SUBSCRIBFY.cartToken)}&st=${amount}&t=${Date.now()}`;
const response = await subscribfyApi.post(url, data);
if (response.error || response.status_code) {
throw new Error(response.error || 'Failed to apply credits');
}
// Update cart attributes
await fetch('/cart/update.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
attributes: {
'subscribfy_checkout_storecredits_label': 'Store Credits',
'subscribfy_checkout_storecredits_value': response.sac,
'subscribfy_checkout_storecredits_hash': response.sch
}
})
});
return response;
}
// Remove store credits
async function removeStoreCredits() {
// Clear cart attributes
await fetch('/cart/update.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
attributes: {
'subscribfy_checkout_storecredits_label': '',
'subscribfy_checkout_storecredits_value': '',
'subscribfy_checkout_storecredits_hash': '',
'subscribfy_store_credits_code': '',
'subscribfy_store_credits': '',
'subscribfy_store_credits_id': ''
}
})
});
// Notify API
await subscribfyApi.post(
`${SUBSCRIBFY.apiPrefix}/softlogin?action=discount&cid=${SUBSCRIBFY.customerId}&exm=1&cp=${window.location.pathname}&t=${Date.now()}`
);
}
// Usage Example
async function init() {
try {
// Check customer
const customer = await checkCustomer('john@example.com');
console.log(`Balance: $${customer.current_balance}`);
// Apply $25 in credits
if (customer.current_balance >= 25) {
const result = await applyStoreCredits(25);
console.log(`Applied: $${result.sac}`);
}
} catch (error) {
console.error('Error:', error.message);
}
}Error Handling
| Error | Solution |
|---|---|
| Customer not found | Verify email is registered |
| Balance is 0 | Customer has no credits to use |
| Session invalid | Customer not logged in properly |
| Token expired | Ensure customer is logged in |
Cart Attributes Reference
| Attribute | Description |
|---|---|
subscribfy_checkout_storecredits_label | Display label ("Store Credits") |
subscribfy_checkout_storecredits_value | Credit amount applied |
subscribfy_checkout_storecredits_hash | Verification hash |
subscribfy_store_credits_code | Legacy: discount code |
subscribfy_store_credits | Legacy: credit amount |
subscribfy_store_credits_id | Legacy: transaction ID |
Customer Metafield
The customer's store credit balance is also available via Liquid:
{{ customer.metafields.exison.exison_st }}Best Practices
- Always fetch fresh cart - Call
/cart.jsbefore each credit application - Include timestamp - Add
&t={timestamp}to prevent caching - Handle login state - Check if customer is logged in before API calls
- Validate amounts - Don't request more credits than available balance
- Clear on cancel - Always remove credits if customer cancels checkout
Was this page helpful?