Build a custom action

⚡ New — Available in PR #732

When the built-in integrations don’t cover what you need, build a custom action. Custom actions can call any HTTPS endpoint — your own API, a third-party API, a Zapier webhook — using OAuth, API keys, or no auth.

In this guide:

  • When to build custom
  • Open the Action Builder
  • Pick a starter template
  • Configure the fields
  • Test
  • Save

When to build custom

  • Your own API. Look up an order in your custom OMS, query your inventory system.
  • A third-party API not in our integrations list. HubSpot, Intercom, Linear — anything with an HTTPS endpoint.
  • A Zapier or Make webhook. Use the chatbot to fire workflows in tools we don’t directly integrate.
  • Internal logic. Wrap your own business rule (/api/eligible-for-discount) as an action.

If we have a built-in integration (Stripe, Shopify, Salesforce, Zendesk), use that — the templates handle authentication and edge cases for you.

Step 1: Open the Action Builder

On the chatbot detail page → ActionsNew action. The Template Picker appears.

Action Template picker Screenshot: The action builder with form fields for endpoint, method, auth, schema, and prompt.

Step 2: Pick a starter template

The Template Picker has:

  • HTTP GET — fetch a record by ID. Read-only, no confirmation by default.
  • HTTP POST — create a record. Often confirmation-gated.
  • Stripe presets — pre-configured for invoice and subscription operations. → Stripe presets.
  • Shopify write-backs — pre-configured for order and inventory operations. → Shopify write-backs.
  • From scratch — empty form for full control.

Pick the closest match. The Action Builder opens with that template’s fields pre-filled.

Step 3: Configure the fields

Walk through each field:

Name and description

  • Name — what the bot sees. “Look up customer subscription tier” — narrate the verb + object.
  • Description — when to call it. “Use this when the user asks about their plan, billing cycle, or membership level.” The clearer the description, the better the bot routes to it.

Endpoint and method

  • Endpoint — the URL. Supports {variable} placeholders for org-scoped values ({orgId}, {chatbotId}) and conversation-scoped values ({userEmail} if the chat captured one).
  • MethodGET for reads, POST/PUT/PATCH/DELETE for writes.

Authentication

  • None — for public APIs.
  • API key — paste the key once; it’s stored encrypted on Hilal’s backend.
  • OAuth — for third-party APIs that require user-level auth. Configure the OAuth client ID, secret, and scopes; the bot triggers a one-time consent flow per user.

Headers

Add required headers like Content-Type: application/json or vendor-specific ones like Stripe-Version.

Body template

For POST/PUT/PATCH, write a JSON template:

{
  "email": "{user.email}",
  "subject": "{conversation.summary}",
  "priority": "normal"
}

Placeholders are filled at call time from the conversation context. Hilal Chatbot’s variable engine handles common ones like user.email, conversation.summary, chatbot.id.

Output mapping

Tell the bot how to interpret the response. For example, if the API returns { "data": { "id": "rec_123" } }, map responseId = data.id so the bot can reference it later.

For freeform replies (the bot just shows the response back to the user), no mapping needed.

Confirmation flag

Toggle Requires confirmation for any destructive action. → Confirmation flows.

Rate limit

Set rate_limit_per_minute. Default is conservative (10/min); raise for high-volume reads, lower for sensitive writes.

Step 4: Test

Click Test action in the Builder. You’ll get a test panel where you can plug in placeholder values and run the action manually. The response is shown raw.

If it succeeds, save. If not, check headers, auth, and endpoint.

Step 5: Save

Click Save. The action is now live for this chatbot. The bot will start considering it on the next message.

Tips

  • Start with read-only actions. Get retrieval working before adding writes.
  • Use idempotency keys when possible. If your backend respects the Idempotency-Key header (Stripe, Shopify, etc.), the framework will send one automatically.
  • Test edge cases manually. What happens when the API returns 404? 500? Timeout? Document expected behavior in the action description so the bot handles it gracefully.

Troubleshooting

  • Action never fires. Description may not match the user’s wording. Re-write to match common phrasings.
  • Action fires too often. Description is too broad. Narrow it (“Use this only when the user explicitly asks about their billing”).
  • Auth fails. OAuth scopes may be insufficient, or the API key may be wrong. Test the call with curl first.

What’s next