Hookbase
Docs
GuideAPI ReferenceIntegrationsUse CasesCLIMCP
Getting StartedSDK ReferencePortal ComponentsAPI Reference
Get Started

Getting Started

OverviewIntegration Guide

SDK & Portal

SDK ReferencePortal OverviewMagic LinksComponentsHooksStylingPortal API Reference

API Reference

REST API
DocsSendPortalMagic Links

Magic Links

Magic links generate short-lived portal session tokens, ideal for:

  • Embedding the hosted portal in an iframe without exposing long-lived tokens
  • Generating one-click links in emails or dashboards
  • Time-boxed portal access for support scenarios

How It Works

  1. Your backend calls the magic link endpoint with an application ID
  2. Hookbase returns a URL like https://www.hookbase.app/portal/whpt_abc123... and the raw token
  3. You redirect your customer to the URL or embed it in an iframe
  4. The token expires automatically (default: 60 minutes, max: 24 hours)

API Endpoint

POST /api/organizations/:orgId/portal/webhook-applications/:appId/magic-link

Request Body

FieldTypeDefaultDescription
expiresInMinutesnumber60Token lifetime (1–1440 minutes)
scopesstring[]['read', 'write']Permissions: read, write, or both

Response

{
  "data": {
    "url": "https://www.hookbase.app/portal/whpt_abc123...",
    "token": "whpt_abc123...",
    "expiresAt": "2026-03-14T15:30:00.000Z",
    "expiresInMinutes": 60,
    "scopes": ["read", "write"]
  }
}

Server-Side Examples

Node.js / Express

app.get('/api/portal-link', async (req, res) => {
  const customer = await getCustomerFromSession(req);
 
  const response = await fetch(
    `https://api.hookbase.app/api/organizations/${ORG_ID}/portal/webhook-applications/${customer.appId}/magic-link`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${API_KEY}`,
      },
      body: JSON.stringify({
        expiresInMinutes: 60,
        scopes: ['read', 'write'],
      }),
    }
  );
 
  const { data } = await response.json();
  res.json({ url: data.url });
});

Python / Flask

@app.route('/api/portal-link')
def portal_link():
    customer = get_customer_from_session()
 
    response = requests.post(
        f'https://api.hookbase.app/api/organizations/{ORG_ID}/portal/webhook-applications/{customer.app_id}/magic-link',
        headers={
            'Content-Type': 'application/json',
            'Authorization': f'Bearer {API_KEY}',
        },
        json={
            'expiresInMinutes': 60,
            'scopes': ['read', 'write'],
        },
    )
 
    data = response.json()['data']
    return jsonify({'url': data['url']})

Using the Token with the npm Package

If you prefer to render the portal in your own React app rather than using the hosted page, pass the magic link token directly to <HookbasePortal>:

function PortalPage() {
  const [token, setToken] = useState<string | null>(null);
 
  useEffect(() => {
    fetch('/api/portal-link')
      .then(res => res.json())
      .then(data => {
        // Extract token from URL or use the raw token
        setToken(data.token);
      });
  }, []);
 
  if (!token) return <div>Loading...</div>;
 
  return (
    <HookbasePortal token={token}>
      <EndpointList />
      <MessageLog />
    </HookbasePortal>
  );
}

Iframe Embedding

function PortalEmbed() {
  const [portalUrl, setPortalUrl] = useState<string | null>(null);
 
  useEffect(() => {
    fetch('/api/portal-link')
      .then(res => res.json())
      .then(data => setPortalUrl(data.url));
  }, []);
 
  if (!portalUrl) return <div>Loading...</div>;
 
  return (
    <iframe
      src={portalUrl}
      width="100%"
      height="600"
      style=
      title="Webhook Portal"
    />
  );
}

Security Best Practices

  • Always generate magic links server-side. Never expose your API key to the browser.
  • Use the shortest expiration that works. Default 60 minutes is good for most use cases.
  • Scope tokens to read when write access isn't needed. Read-only tokens prevent customers from creating or modifying endpoints.
  • Don't cache or reuse magic link tokens. Generate a fresh one each time the user opens the portal.
  • Use HTTPS for iframe embeds. Mixed content will be blocked by browsers.

Long-Lived Tokens vs Magic Links

Long-Lived TokenMagic Link
Lifetime1–365 days1–1440 minutes
Use casenpm package with token stored in your backendHosted portal links, iframe embeds
EndpointPOST .../tokensPOST .../magic-link
Returns URLNo (token only)Yes (hookbase.app/portal/{token})
Session tokenNoYes (excluded from token list)
PreviousPortal OverviewNextComponents

On this page

How It WorksAPI EndpointRequest BodyResponseServer-Side ExamplesNode.js / ExpressPython / FlaskUsing the Token with the npm PackageIframe EmbeddingSecurity Best PracticesLong-Lived Tokens vs Magic Links