Get custom CSS for customer portal
Retrieves the custom CSS styling configuration for the customer portal. This endpoint returns all custom CSS rules that have been configured to customize the appearance, layout, and branding of the subscription customer portal.
What is Custom CSS? Custom CSS allows merchants to fully customize the visual appearance of their customer portal beyond the basic theme settings. This enables complete brand alignment and creates a seamless experience that matches the merchant’s main store design.
Custom CSS Capabilities:
-
Layout Customization:
- Modify page layouts and spacing
- Adjust grid and flexbox configurations
- Control responsive breakpoints
- Customize navigation and sidebars
-
Typography:
- Custom fonts and font families
- Font sizes, weights, and line heights
- Letter spacing and text transforms
- Heading and paragraph styles
-
Colors and Branding:
- Brand color palette application
- Custom background colors and gradients
- Button and link styling
- Hover and focus states
- Border colors and shadows
-
Component Styling:
- Subscription card appearances
- Form input styling
- Button designs and interactions
- Modal and dialog boxes
- Navigation menus
- Product images and thumbnails
-
Advanced Features:
- CSS animations and transitions
- Media queries for responsive design
- Pseudo-elements and pseudo-classes
- Custom icons using CSS
- Transform and filter effects
CSS Structure: The returned CSS includes:
- Global styles for portal-wide consistency
- Component-specific styles
- Responsive design rules
- Theme overrides
- Custom animations
- Print styles (optional)
Common CSS Selectors Available:
/* Portal container */
.subscription-portal { }
/* Subscription cards */
.subscription-card { }
.subscription-card-header { }
.subscription-card-body { }
/* Buttons */
.btn-primary { }
.btn-secondary { }
.btn-cancel { }
/* Forms */
.form-control { }
.form-group { }
.form-label { }
/* Navigation */
.portal-nav { }
.nav-item { }
/* Product displays */
.product-item { }
.product-image { }
.product-title { }
Use Cases:
- Apply custom branding to match main store design
- Create unique visual experiences for different customer segments
- Implement seasonal or promotional themes
- Enhance mobile responsiveness
- Add accessibility improvements (high contrast, larger fonts)
- A/B test different portal designs
- Integrate with design systems
- Implement dark mode or theme switching
Important Notes:
- CSS is sanitized for security (XSS prevention)
- Certain properties may be restricted for security reasons
- External resources (fonts, images) must use HTTPS
- CSS is cached for performance - changes may take a few minutes to propagate
- Invalid CSS syntax is automatically filtered out
- Some core portal elements have !important styles that cannot be overridden
Best Practices:
- Use specific selectors to avoid conflicts
- Test across different browsers and devices
- Keep CSS organized with comments
- Use CSS variables for maintainability
- Minify CSS for production performance
- Consider accessibility in color choices (WCAG compliance)
- Provide fallbacks for advanced CSS features
Security Considerations:
- CSS is sanitized to prevent code injection
- External URLs are validated
- JavaScript in CSS is blocked (e.g., expression(), behavior())
- Data URIs are validated for malicious content
Authentication: Requires valid X-API-Key header
curl --request GET \
--url https://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}import requests
url = "https://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const url = 'https://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}';
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://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}",
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://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}"
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://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}")
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"{\n \"id\": 12345,\n \"shop\": \"example-shop.myshopify.com\",\n \"customCss\": \"/* Global Portal Styles */\\n\" +\n \".subscription-portal {\\n\" +\n \" font-family: 'Helvetica Neue', Arial, sans-serif;\\n\" +\n \" background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\\n\" +\n \" min-height: 100vh;\\n\" +\n \"}\\n\\n\" +\n \"/* Subscription Cards */\\n\" +\n \".subscription-card {\\n\" +\n \" border-radius: 12px;\\n\" +\n \" box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\\n\" +\n \" background: white;\\n\" +\n \" padding: 24px;\\n\" +\n \" margin-bottom: 16px;\\n\" +\n \" transition: transform 0.2s ease, box-shadow 0.2s ease;\\n\" +\n \"}\\n\\n\" +\n \".subscription-card:hover {\\n\" +\n \" transform: translateY(-2px);\\n\" +\n \" box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);\\n\" +\n \"}\\n\\n\" +\n \"/* Primary Button Styling */\\n\" +\n \".btn-primary {\\n\" +\n \" background-color: #4A90E2;\\n\" +\n \" border-color: #4A90E2;\\n\" +\n \" color: white;\\n\" +\n \" font-weight: 600;\\n\" +\n \" padding: 12px 24px;\\n\" +\n \" border-radius: 6px;\\n\" +\n \" transition: all 0.3s ease;\\n\" +\n \"}\\n\\n\" +\n \".btn-primary:hover {\\n\" +\n \" background-color: #357ABD;\\n\" +\n \" border-color: #357ABD;\\n\" +\n \" transform: scale(1.02);\\n\" +\n \"}\\n\\n\" +\n \"/* Form Inputs */\\n\" +\n \".form-control {\\n\" +\n \" border: 2px solid #E0E0E0;\\n\" +\n \" border-radius: 6px;\\n\" +\n \" padding: 10px 14px;\\n\" +\n \" font-size: 14px;\\n\" +\n \"}\\n\\n\" +\n \".form-control:focus {\\n\" +\n \" border-color: #4A90E2;\\n\" +\n \" box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.1);\\n\" +\n \" outline: none;\\n\" +\n \"}\\n\\n\" +\n \"/* Responsive Design */\\n\" +\n \"@media (max-width: 768px) {\\n\" +\n \" .subscription-card {\\n\" +\n \" padding: 16px;\\n\" +\n \" }\\n\" +\n \" .btn-primary {\\n\" +\n \" width: 100%;\\n\" +\n \" }\\n\" +\n \"}\",\n \"enabled\": true,\n \"version\": 2,\n \"lastModified\": \"2024-02-20T14:45:00Z\",\n \"createdAt\": \"2024-01-15T10:30:00Z\",\n \"updatedAt\": \"2024-02-20T14:45:00Z\"\n}"{
"detail": "Valid X-API-Key header is required",
"status": 401,
"title": "Authentication required",
"type": "https://example.com/errors/unauthorized"
}{
"detail": "API key does not have permission to view custom CSS settings",
"status": 403,
"title": "Insufficient permissions",
"type": "https://example.com/errors/forbidden"
}{
"detail": "No custom CSS has been configured for this shop",
"status": 404,
"title": "CSS not found",
"type": "https://example.com/errors/not-found"
}Headers
Path Parameters
Id
Query Parameters
API Key (Deprecated - Use Header X-API-Key instead)
curl --request GET \
--url https://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}import requests
url = "https://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const url = 'https://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}';
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://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}",
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://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}"
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://subscription-admin.appstle.com/api/external/v2/subscription-custom-csses/{id}")
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"{\n \"id\": 12345,\n \"shop\": \"example-shop.myshopify.com\",\n \"customCss\": \"/* Global Portal Styles */\\n\" +\n \".subscription-portal {\\n\" +\n \" font-family: 'Helvetica Neue', Arial, sans-serif;\\n\" +\n \" background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\\n\" +\n \" min-height: 100vh;\\n\" +\n \"}\\n\\n\" +\n \"/* Subscription Cards */\\n\" +\n \".subscription-card {\\n\" +\n \" border-radius: 12px;\\n\" +\n \" box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\\n\" +\n \" background: white;\\n\" +\n \" padding: 24px;\\n\" +\n \" margin-bottom: 16px;\\n\" +\n \" transition: transform 0.2s ease, box-shadow 0.2s ease;\\n\" +\n \"}\\n\\n\" +\n \".subscription-card:hover {\\n\" +\n \" transform: translateY(-2px);\\n\" +\n \" box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);\\n\" +\n \"}\\n\\n\" +\n \"/* Primary Button Styling */\\n\" +\n \".btn-primary {\\n\" +\n \" background-color: #4A90E2;\\n\" +\n \" border-color: #4A90E2;\\n\" +\n \" color: white;\\n\" +\n \" font-weight: 600;\\n\" +\n \" padding: 12px 24px;\\n\" +\n \" border-radius: 6px;\\n\" +\n \" transition: all 0.3s ease;\\n\" +\n \"}\\n\\n\" +\n \".btn-primary:hover {\\n\" +\n \" background-color: #357ABD;\\n\" +\n \" border-color: #357ABD;\\n\" +\n \" transform: scale(1.02);\\n\" +\n \"}\\n\\n\" +\n \"/* Form Inputs */\\n\" +\n \".form-control {\\n\" +\n \" border: 2px solid #E0E0E0;\\n\" +\n \" border-radius: 6px;\\n\" +\n \" padding: 10px 14px;\\n\" +\n \" font-size: 14px;\\n\" +\n \"}\\n\\n\" +\n \".form-control:focus {\\n\" +\n \" border-color: #4A90E2;\\n\" +\n \" box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.1);\\n\" +\n \" outline: none;\\n\" +\n \"}\\n\\n\" +\n \"/* Responsive Design */\\n\" +\n \"@media (max-width: 768px) {\\n\" +\n \" .subscription-card {\\n\" +\n \" padding: 16px;\\n\" +\n \" }\\n\" +\n \" .btn-primary {\\n\" +\n \" width: 100%;\\n\" +\n \" }\\n\" +\n \"}\",\n \"enabled\": true,\n \"version\": 2,\n \"lastModified\": \"2024-02-20T14:45:00Z\",\n \"createdAt\": \"2024-01-15T10:30:00Z\",\n \"updatedAt\": \"2024-02-20T14:45:00Z\"\n}"{
"detail": "Valid X-API-Key header is required",
"status": 401,
"title": "Authentication required",
"type": "https://example.com/errors/unauthorized"
}{
"detail": "API key does not have permission to view custom CSS settings",
"status": 403,
"title": "Insufficient permissions",
"type": "https://example.com/errors/forbidden"
}{
"detail": "No custom CSS has been configured for this shop",
"status": 404,
"title": "CSS not found",
"type": "https://example.com/errors/not-found"
}