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

FeatureStarterProEnterprise
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--
Upgrade Path: Start with Starter for basic branding, upgrade to Pro when you need a custom domain, and Enterprise for complete white-labeling. View pricing at /pricing.

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"
}
FieldTypeDescription
logo_urlstringURL to your logo image (SVG, PNG, or JPG)
custom_domainstringCustom domain for portal (requires DNS setup)
colorsobjectColor palette (hex format)
fontsobjectFont families for heading and body
custom_cssstringAdvanced CSS overrides (Pro plan)
help_urlstringLink to your webhook documentation
show_hookmesh_brandingbooleanShow "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/branding

Request 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

Node.js
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);
Python
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

PropertyRequirement
FormatSVG (recommended), PNG, JPG
Max size1 MB
Recommended dimensions200px wide, 50px tall (height auto-scales)
Transparent backgroundRecommended for SVG and PNG

Upload Options

You can provide your logo in two ways: via URL or as a base64-encoded string.

Logo via URL (recommended)
// 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'
  })
});
Logo via Base64
// 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
  })
});
Best practice: Host your logo on a CDN for better performance and easier updates. Base64 encoding is convenient for small images but increases payload size.

Color Customization

Customize the portal's color scheme to match your brand. All colors should be specified in hex format (e.g., #6366f1).

ColorUsageExample
primaryButtons, links, highlights#6366f1
secondarySecondary actions, accents#8b5cf6
backgroundPage background#ffffff
textPrimary text color#1f2937
text_secondaryLabels, helper text#6b7280
borderDividers, input borders#e5e7eb
Update Colors
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
    }
  })
});
Contrast requirements: Ensure sufficient contrast between text and background colors for accessibility (WCAG AA: 4.5:1 for normal text, 3:1 for large text).

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.

Custom Fonts
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'
    }
  })
});
With Google Fonts
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 TypeNameValue
CNAMEwebhooksportal.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_xxx

Custom 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

ClassElement
.portal-headerPage header with logo
.portal-navNavigation sidebar
.portal-button-primaryPrimary action buttons
.portal-button-secondarySecondary buttons
.portal-tableData tables
.portal-cardContent cards
.portal-formForm 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/preview
const 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 hour
Test before applying: Preview URLs are valid for 1 hour and don't affect your live portal. Share the preview with your team to gather feedback before committing changes.

Removing 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
  })
});
Enterprise only: This feature requires an Enterprise plan. Starter and Pro plans include "Powered by Hook Mesh" branding in the portal footer.

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:

ElementReason
Authentication flowsSecurity and compliance
Security warningsMust remain clearly visible
Error messagesClarity and debugging
SSL certificate badgesTrust 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