Portal Customization
Make the Hook Mesh customer portal feel like your own product. Customize branding, colors, fonts, and domain to create a seamless experience for your customers.
What You Can Customize
The customer portal supports comprehensive white-labeling to match your brand identity:
- Custom domain - Host the portal at
webhooks.yourcompany.com - Logo - Upload your company logo (URL or base64)
- Colors - Primary, secondary, background, text, and border colors
- Fonts - Custom typefaces for headings and body text
- Custom CSS - Advanced styling for precise control (optional)
- Help links - Point to your own documentation
- Language/localization - Custom labels and translations
- Remove Hook Mesh branding - Enterprise plan only
Plan Feature Matrix
| Feature | Starter | Pro | Enterprise |
|---|---|---|---|
| Custom logo (URL or base64) | ✓ | ✓ | ✓ |
| Color customization (6 colors) | ✓ | ✓ | ✓ |
| Custom fonts (Google Fonts) | ✓ | ✓ | ✓ |
| Help link customization | ✓ | ✓ | ✓ |
| Support email customization | ✓ | ✓ | ✓ |
| Language/localization (7 languages) | ✓ | ✓ | ✓ |
| Custom domain (CNAME + SSL) | - | ✓ | ✓ |
| Custom CSS (advanced styling) | - | ✓ | ✓ |
| Custom domain SSL auto-provisioning | - | ✓ | ✓ |
| Remove "Powered by Hook Mesh" | - | - | ✓ |
| Custom labels & terminology | - | - | ✓ |
| Dedicated support engineer | - | - | ✓ |
The Branding Object
All customization settings are stored in the branding object for your organization:
{
"logo_url": "https://cdn.yourcompany.com/logo.svg",
"custom_domain": "webhooks.yourcompany.com",
"colors": {
"primary": "#6366f1",
"secondary": "#8b5cf6",
"background": "#ffffff",
"text": "#1f2937",
"text_secondary": "#6b7280",
"border": "#e5e7eb"
},
"fonts": {
"heading": "Inter, sans-serif",
"body": "Inter, sans-serif"
},
"custom_css": ".portal-header { border-radius: 12px; }",
"help_url": "https://docs.yourcompany.com/webhooks",
"support_email": "support@yourcompany.com",
"language": "en",
"show_hookmesh_branding": false,
"updated_at": "2026-01-20T15:30:00Z"
}| Field | Type | Description |
|---|---|---|
logo_url | string | URL to your logo image (SVG, PNG, or JPG) |
custom_domain | string | Custom domain for portal (requires DNS setup) |
colors | object | Color palette (hex format) |
fonts | object | Font families for heading and body |
custom_css | string | Advanced CSS overrides (Pro plan) |
help_url | string | Link to your webhook documentation |
show_hookmesh_branding | boolean | Show "Powered by Hook Mesh" (Enterprise only) |
Update Branding Configuration
Update your organization's branding settings using the branding API endpoint. Changes take effect immediately for all customer portals.
PUT /v1/organizations/brandingRequest Body
{
"logo_url": "https://cdn.acme.com/logo.svg",
"colors": {
"primary": "#6366f1",
"secondary": "#8b5cf6",
"background": "#ffffff",
"text": "#1f2937"
},
"fonts": {
"heading": "Inter, sans-serif",
"body": "Inter, sans-serif"
},
"help_url": "https://docs.acme.com/webhooks"
}Code Examples
const response = await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${process.env.HOOKMESH_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
logo_url: 'https://cdn.acme.com/logo.svg',
colors: {
primary: '#6366f1',
secondary: '#8b5cf6',
background: '#ffffff',
text: '#1f2937',
text_secondary: '#6b7280',
border: '#e5e7eb'
},
fonts: {
heading: 'Inter, sans-serif',
body: 'Inter, sans-serif'
},
help_url: 'https://docs.acme.com/webhooks',
support_email: 'support@acme.com'
})
});
const branding = await response.json();
console.log('Branding updated:', branding);import requests
import os
response = requests.put(
'https://api.hookmesh.com/v1/organizations/branding',
headers={'Authorization': f'Bearer {os.environ.get("HOOKMESH_API_KEY")}'},
json={
'logo_url': 'https://cdn.acme.com/logo.svg',
'colors': {
'primary': '#6366f1',
'secondary': '#8b5cf6',
'background': '#ffffff',
'text': '#1f2937',
'text_secondary': '#6b7280',
'border': '#e5e7eb'
},
'fonts': {
'heading': 'Inter, sans-serif',
'body': 'Inter, sans-serif'
},
'help_url': 'https://docs.acme.com/webhooks',
'support_email': 'support@acme.com'
}
)
branding = response.json()
print(f'Branding updated: {branding}')Logo Customization
Upload your company logo to display in the portal header. Supports SVG, PNG, and JPG formats.
Logo Requirements
| Property | Requirement |
|---|---|
| Format | SVG (recommended), PNG, JPG |
| Max size | 1 MB |
| Recommended dimensions | 200px wide, 50px tall (height auto-scales) |
| Transparent background | Recommended for SVG and PNG |
Upload Options
You can provide your logo in two ways: via URL or as a base64-encoded string.
// Host your logo on a CDN and reference it
await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
logo_url: 'https://cdn.acme.com/logo.svg'
})
});// Or upload a base64-encoded image
import fs from 'fs';
const logoBuffer = fs.readFileSync('./logo.png');
const logoBase64 = `data:image/png;base64,${logoBuffer.toString('base64')}`;
await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
logo_url: logoBase64
})
});Color Customization
Customize the portal's color scheme to match your brand. All colors should be specified in hex format (e.g., #6366f1).
| Color | Usage | Example |
|---|---|---|
primary | Buttons, links, highlights | #6366f1 |
secondary | Secondary actions, accents | #8b5cf6 |
background | Page background | #ffffff |
text | Primary text color | #1f2937 |
text_secondary | Labels, helper text | #6b7280 |
border | Dividers, input borders | #e5e7eb |
await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
colors: {
primary: '#6366f1', // Indigo
secondary: '#8b5cf6', // Purple
background: '#ffffff', // White
text: '#1f2937', // Dark gray
text_secondary: '#6b7280', // Medium gray
border: '#e5e7eb' // Light gray
}
})
});Font Customization
Specify custom fonts for headings and body text. Use web-safe fonts or load custom fonts from Google Fonts, Adobe Fonts, or your own CDN.
await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
fonts: {
heading: 'Montserrat, sans-serif',
body: 'Open Sans, sans-serif'
}
})
});@import statement in your custom_css field to ensure fonts load properly.await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
fonts: {
heading: 'Montserrat, sans-serif',
body: 'Open Sans, sans-serif'
},
custom_css: `
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@600;700&family=Open+Sans:wght@400;500&display=swap');
`
})
});Custom Domain Setup
Host the customer portal on your own domain (e.g., webhooks.yourcompany.com) for a fully white-labeled experience.
DNS Configuration
Create a CNAME record pointing your subdomain to Hook Mesh's portal infrastructure:
| Record Type | Name | Value |
|---|---|---|
CNAME | webhooks | portal.hookmesh.com |
SSL Certificate
SSL certificates are provisioned automatically via Let's Encrypt once your DNS is configured. This typically takes 5-10 minutes.
Enable Custom Domain
// Step 1: Configure DNS (CNAME record)
// Step 2: Set custom domain in Hook Mesh
await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
custom_domain: 'webhooks.acme.com'
})
});
// Step 3: Wait for SSL certificate provisioning (5-10 minutes)
// Step 4: Test your custom domain
// https://webhooks.acme.com/portal/app_xxxCustom CSS (Advanced)
For precise control over the portal's appearance, use custom CSS. This is an advanced feature requiring Pro plan or higher.
await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
custom_css: `
/* Customize header */
.portal-header {
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
/* Customize buttons */
.portal-button-primary {
border-radius: 8px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
/* Customize tables */
.portal-table {
border-radius: 8px;
overflow: hidden;
}
.portal-table-row:hover {
background-color: rgba(99, 102, 241, 0.05);
}
`
})
});Available CSS Classes
| Class | Element |
|---|---|
.portal-header | Page header with logo |
.portal-nav | Navigation sidebar |
.portal-button-primary | Primary action buttons |
.portal-button-secondary | Secondary buttons |
.portal-table | Data tables |
.portal-card | Content cards |
.portal-form | Form elements |
Custom Help Links & Support
Point customers to your own documentation and support resources instead of Hook Mesh's help pages.
await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
help_url: 'https://docs.acme.com/webhooks',
support_email: 'support@acme.com',
documentation_links: {
getting_started: 'https://docs.acme.com/webhooks/getting-started',
troubleshooting: 'https://docs.acme.com/webhooks/troubleshooting',
api_reference: 'https://docs.acme.com/api/webhooks'
}
})
});Preview Changes
Before applying changes globally, preview how your branding looks in the portal. Use the preview endpoint to generate a preview URL with your changes.
POST /v1/organizations/branding/previewconst response = await fetch('https://api.hookmesh.com/v1/organizations/branding/preview', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
colors: {
primary: '#6366f1',
background: '#ffffff'
},
logo_url: 'https://cdn.acme.com/new-logo.svg'
})
});
const { preview_url, expires_at } = await response.json();
console.log('Preview URL:', preview_url);
// https://portal.hookmesh.com/preview/org_xyz?token=preview_abc123
// Valid for 1 hourRemoving Hook Mesh Branding
Enterprise plan customers can remove the "Powered by Hook Mesh" footer to create a fully white-labeled experience.
await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
show_hookmesh_branding: false
})
});Language & Localization
Customize portal text and labels to support different languages or customize terminology to match your product.
await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
language: 'es', // Spanish
custom_labels: {
endpoints: 'Destinos',
webhook_jobs: 'Trabajos de Webhook',
event_types: 'Tipos de Eventos',
success_rate: 'Tasa de Éxito',
retry: 'Reintentar',
test_webhook: 'Probar Webhook'
}
})
});Supported languages: English (en), Spanish (es), French (fr), German (de), Portuguese (pt), Japanese (ja), Chinese (zh).
Customization Limitations
For security and compliance reasons, certain UI elements cannot be customized:
| Element | Reason |
|---|---|
| Authentication flows | Security and compliance |
| Security warnings | Must remain clearly visible |
| Error messages | Clarity and debugging |
| SSL certificate badges | Trust indicators |
Testing Customization
After applying branding changes, test the portal thoroughly to ensure everything looks correct:
- Logo rendering: Check logo displays correctly at different screen sizes
- Color contrast: Verify text is readable against backgrounds
- Font loading: Ensure custom fonts load properly (check Network tab)
- Custom domain: Test HTTPS connection and SSL certificate
- Mobile responsiveness: View portal on mobile devices
- Dark mode: If using custom CSS, test in both light and dark modes
- Browser compatibility: Test in Chrome, Firefox, Safari, Edge
Reverting to Defaults
To reset branding to Hook Mesh defaults, send an empty branding object or specify default values:
// Remove all customization
await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
logo_url: null,
custom_domain: null,
colors: null,
fonts: null,
custom_css: null
})
});
// Or reset individual properties
await fetch('https://api.hookmesh.com/v1/organizations/branding', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
colors: null // Reverts to default Hook Mesh colors
})
});Best Practices
- Preview before applying: Always use the preview endpoint to test changes before going live
- Use SVG logos: SVG format scales perfectly and has smaller file sizes
- Test color contrast: Ensure WCAG AA compliance for accessibility
- Host fonts on CDN: Use Google Fonts or Adobe Fonts for reliable font loading
- Set up custom domain: Provides the most seamless white-label experience
- Keep CSS simple: Minimal custom CSS is easier to maintain and less prone to breaking
- Test on mobile: Verify branding looks good on all screen sizes
- Document your changes: Keep track of custom CSS and branding settings for future reference
Next Steps
- Portal overview - Understand customer portal features
- Portal authentication - Set up secure customer access
- Embedding the portal - Integrate portal into your app
- Applications API - Manage customer applications