Skip to content

Docs

Set up AutomatePal

Everything here is built and covered by the repo’s checks. This is a fictional-data preview: payment execution stays off, and some features are built locally but not yet on the hosted preview. See Limits and what is not built.

Last updated

Install the widget

  1. Sign in and open guided setup.
  2. Add a source in Knowledge: paste text, upload Markdown, CSV or a small text PDF, import a public URL or crawl a site. Nothing answers customers until you consent to processing and publish it.
  3. Test a few questions. Answers quote the passage they came from; when nothing supports an answer, the question goes to your review queue.
  4. Shape the widget in Widget studio: colour, starter questions, side, allowed origins and paths, and working hours.
  5. Paste one script tag before </body>.
<script src="https://automatepal.com/widget.js" data-demo-token="YOUR_TOKEN" defer></script>

In this preview the token comes from a one-hour demo link created in Widget studio. Origin and path rules control where the widget shows; they are not authentication for someone who holds the link.

The chat refuses a message that carries its own system prompt, a pasted chat transcript or a request to ignore the bot’s instructions. The visitor sees “This message can’t be sent. Please rephrase your question.” and the text stays in the box. The server runs the same check before any model call, and the answer prompt tells the model never to show, translate or rewrite its instructions. Ordinary questions that mention instructions or a system go through. This is a filter, not a guarantee.

Widget SDK and events

The script tag adds window.AutomatePal to your page. It exists as soon as the script runs; calls made before the widget is ready apply when it appears, and do nothing on a page where the widget is hidden.

CallWhat it does
AutomatePal.open()Opens the chat panel (it loads on first open).
AutomatePal.close()Closes the panel.
AutomatePal.toggle()Opens or closes it.
AutomatePal.reset()Closes the panel, forgets its open state and starts a fresh panel on the next open. Questions already sent stay recorded for you, and the demo link is unchanged.
AutomatePal.on(type, fn)Calls fn(payload) for an event and returns a function that stops listening. AutomatePal.off(type, fn) does the same.
EventWhenPayload
openThe panel opened{type, trigger}, trigger api, button or auto
closeThe panel closed{type, trigger}, trigger api, button or reset
message_sentThe visitor sent a question, a request or a message to the team{type, channel}, channel ai, request or person
handoff_requestedThe visitor asked for a person{type, withinHours}
lead_submittedThe visitor shared an email with consent{type}

Payloads never contain message text, names, email addresses, order details or the demo token. The same payloads are also dispatched on window as automatepal:open, automatepal:message_sent and so on. The panel posts events only to your page’s origin, and the script ignores messages from anywhere else.

window.addEventListener('automatepal:lead_submitted', () => {
  // count a lead in your own analytics; no email is included
});
document.querySelector('#help-link').onclick = () => AutomatePal.open();

Follow-up suggestions

  • In Widget studio, add up to six follow-up questions, one per line, 3 to 80 characters each. Plain text only: angle brackets and control characters are refused.
  • After an answer, the widget shows the first three as buttons, in your order, leaving out the question the visitor just asked. Clicking one asks it.
  • The list is the same for every answer. It is not generated by a model.

Connect billing

Billing support answers order and charge status, payment history, failed payments and retries, invoices, renewal dates and refund status from your payment provider, where the provider supports the lookup. The capability matrix below shows which lookups each provider has. It is read-only: every provider request is matched against a fixed list of read endpoints (plus PayPal’s token sign-in) before it leaves the server, and anything else is refused. No money moves.

Server setup

VariableWhat it holds
BILLING_ENCRYPTION_KEYSComma-separated kid:base64 keys, 32 bytes each, for example k1:$(openssl rand -base64 32).
BILLING_ENCRYPTION_ACTIVE_KIDThe key id new credentials are encrypted with, for example k1.
BILLING_RPC_SECRETA separate random secret (openssl rand -hex 32) that proves database calls come from the server. Rotating keys does not change it.

Until these are set, /billing shows a setup banner and no credential can be saved. Credentials are encrypted with AES-256-GCM, bound to the workspace, provider and mode, never returned to the browser after saving and never logged.

Connect a provider

  1. Open /billing as the workspace owner or an admin and choose a provider.
  2. Choose Test mode or LIVE. LIVE can only be connected by the owner, who types CONNECT LIVE <PROVIDER>, for example CONNECT LIVE STRIPE. Every connection, card and lookup row is labelled Test mode or LIVE.
  3. Paste the credential. A read-only connection check runs before it is saved.
  4. Disconnect deletes the stored credential. The connection history keeps metadata only.

Key rotation

Add a new key, for example k1:…,k2:…, set BILLING_ENCRYPTION_ACTIVE_KID=k2 and restart. Connections still on the old key show Needs rotation on /billing; Rotate re-encrypts them with the active key. Remove the old key once nothing needs rotation.

Providers

10 providers have a built adapter. Each is tested against the provider’s published API contract on a local mock server that checks every request it receives. The source label says what the contract came from.

PayPal

Official API spec

Credential: Client ID + Client secret

REST app client ID and secret. Test uses your sandbox app (api-m.sandbox.paypal.com); live uses a live app (api-m.paypal.com).

Customers verify with: Invoice ID (INV2-…), Subscription ID (I-…), Order ID, Invoice number

Also checked read-only against a real sandbox account. Invoice lookups need the Invoicing feature on the sandbox app.

Stripe

Official API spec

Credential: Restricted key (read permissions)

A restricted key with read permissions: rk_test_ for test, rk_live_ for live. A full sk_test_ key works with a warning. Full sk_live_ keys and publishable pk_ keys are refused.

Customers verify with: Charge ID (ch_…), Payment ID (pi_…), Invoice ID (in_…), Invoice number

Dodo Payments

Official API spec

Credential: API key

An API key from the matching environment (test.dodopayments.com or live.dodopayments.com). A key from the other mode fails the connection check.

Customers verify with: Payment ID (pay_…), Subscription ID (sub_…)

Razorpay

Built from API docs

Credential: Key ID + Key secret

Key ID and key secret: rzp_test_ for test, rzp_live_ for live.

Customers verify with: Payment ID (pay_…), Order ID (order_…), Invoice ID (inv_…), Subscription ID (sub_…)

Paddle

Official API spec

Credential: API key (read permissions)

An API key with read permissions. Sandbox keys contain _sdbx and go to sandbox-api.paddle.com; live keys must not contain it.

Customers verify with: Transaction ID (txn_…), Subscription ID (sub_…), Invoice number

Square

Official API spec

Credential: Access token (read scopes)

An access token with read scopes, from your sandbox or production application. Requests pin a Square-Version header.

Customers verify with: Invoice ID (inv:…), Subscription ID, Payment or order ID

Adyen

Official API spec

Credential: API key (Checkout webservice user) · Settings: Merchant account, Live URL prefix

The API key of a Checkout webservice user plus your merchant account. Live also needs your live URL prefix.

Customers verify with: Payment link ID (PL…)

Order status and payment links only. The Checkout API has no list endpoint for the other lookups.

Mollie

Official API spec

Credential: API key

An API key: test_ for test, live_ for live. OAuth access_ tokens are refused.

Customers verify with: Payment ID (tr_…)

Stored as our own digest of the official spec, because the upstream spec has no license. No invoice links.

Chargebee

Official spec, early access

Credential: API key (read-only) · Settings: Site name

A read-only API key and your site name. Choose test or live to match the site.

Customers verify with: Invoice or subscription ID

Invoice records come without a hosted link.

Lemon Squeezy

Built from API docs

Credential: API key

An API key. The connection check compares the store’s test mode with the mode you choose.

Customers verify with: Order ID or subscription ID

Capability matrix

The bot only offers a lookup the provider supports, and says so when it cannot.

ProviderOrder or charge statusPayment historyFailed payment and retryInvoice linkSubscription renewalRefund status
PayPalYesYesYesYesYesYes
StripeYesYesYesYesYesYes
Dodo PaymentsYesYesYesYesYesYes
RazorpayYesYesYesYesYesYes
PaddleYesYesYesYesYesYes
SquareYesYesYesYesYesYes
AdyenYesNoNoYesNoNo
MollieYesYesYesNoYesYes
ChargebeeYesYesYesYesYesYes
Lemon SqueezyYesYesYesYesYesYes

Providers can be tried with test keys: npm run billing:live-check -- <provider> makes read-only calls with the keys named in .env.example.

Customer verification

  • Before any billing record is shown, the customer enters an order, invoice or payment ID and the email they paid with. Both must match the provider’s record.
  • A match is valid for 30 minutes and never outlasts the chat link. Every later lookup stays inside that customer’s records, and each returned record is checked again before it is shown.
  • “Not found” and “does not match” get the same reply, so the form cannot be used to test whether an order exists.
  • The email is compared and discarded. It is never stored or logged, and the lookup log keeps metadata only: provider, mode, lookup type, outcome, a shortened record ID, status and amount.
  • Limits: 5 failed verifications and 30 lookups per chat; per workspace 60 lookups per 10 minutes and 300 per UTC day; 30 per provider per 10 minutes.

Refund reviews (never executed)

A verified customer can ask for a refund review on a payment. That opens the existing refund-review ticket with the payment attached. You record approve or decline in Tickets. Nothing executes: no refund, capture or charge call exists, and the provider is never written to.

Owner replies

  • Take over a conversation in Tickets. AI answers pause, including one already being prepared, and the header shows “Taken over · AI paused”.
  • Use Reply in widget in the composer. The visitor sees the message in the widget within a few seconds while their page is open, and can answer in the same thread.
  • Replies are shown in the widget only. Nothing is emailed.
  • Up to 100 messages per conversation (50 from the visitor), 1,000 characters each. Replies stop when you release or close the conversation or its link expires.
  • Ticket history records “Owner replied in the widget” without the text. Messages are deleted with the conversation and by preview-data deletion.

Working hours

  • In Widget studio, turn on working hours, pick a time zone and set one opening range per day. Overnight ranges are allowed.
  • Write an away message of up to 300 characters.
  • With “Let visitors choose AI or a person” on, the widget offers Ask the AI or Talk to a person.
  • Outside your hours, a request for a person shows your away message and “Your request is saved for the team.” The visitor can still leave an email for a follow-up unless you hide contact.
  • Working hours describe when you reply. They are not a staffing or response-time promise.

Leads

  • A lead is a contact email a visitor left in the widget with consent. The Leads page lists the latest 500 for managers, admins and the owner. Agents cannot open it.
  • Search matches the email or the request kind. Export downloads the leads shown as CSV, with cells that start with = + - @ escaped so spreadsheets treat them as text.
  • Deleting a lead removes the address and the consent from that request. The request stays in Tickets. Deletions are audited.
  • Leads are not forwarded to email or a CRM.

MCP server

Endpoint https://automatepal.com/mcp, Streamable HTTP, stateless JSON responses, POST only. It serves one workspace, chosen by the token.

Tokens and scopes

Create a token on the Integrations page. Tokens are hashed at rest, expire after 1 to 168 hours, can be revoked, and at most five are active per workspace. Send it as Authorization: Bearer ap_ro_…. Each token has one scope, and only that scope’s tools are listed.

ScopeTools
mcp:readAll five read tools
support:readTickets and billing connection status (also the read-only API)
analytics:readOwner overview counts (also the read-only API)
knowledge:writePropose a text source, and list sources
bot:testAsk the bot a test question
conversations:replyReply in a conversation you already took over, and list tickets
settings:readRead the support settings
settings:writeRead and change the support settings

Tools

ToolWhat it returnsScopesAnnotations
list_knowledge_sourcesKnowledge sources: titles, state, size (no source text)mcp:read, knowledge:writereadOnlyHint
get_unanswered_digestUnanswered questions from the last 7 daysmcp:readreadOnlyHint
list_ticketsLatest 100 tickets: status, priority, inbox statemcp:read, support:read, conversations:replyreadOnlyHint
get_owner_overviewOverview counts: tickets, questions, requests, knowledgemcp:read, analytics:readreadOnlyHint
get_billing_connection_statusPayment provider connections and 24 h lookup countsmcp:read, support:readreadOnlyHint
add_text_knowledge_sourcePropose a text source (stays unpublished until you approve)knowledge:writenot read-only, not destructive, closed world
ask_test_questionPreview a bot answer (not recorded)bot:testnot read-only, not destructive, open world (calls the model)
reply_to_conversationReply in the widget to a conversation you already took overconversations:replynot read-only, not destructive, open world (the visitor sees it)
read_settingsWorking hours, away message, AI-or-person choice, contact fieldsettings:read, settings:writereadOnlyHint
update_settingsChange working hours, away message, AI-or-person choice, contact fieldsettings:writenot read-only, destructive (overwrites the saved values), idempotent, closed world

Read tools return metadata and counts, except get_unanswered_digest, which includes the text of visitor questions it could not answer. No tool returns owner or visitor message bodies, contact addresses, credentials or source text. reply_to_conversation is the only tool a visitor sees: it posts a team reply in the widget, only in a conversation you already took over in Tickets, and it never takes one over. update_settings changes only the chat mode (working hours on or off), working hours, away message, the AI-or-person choice and the contact field. There are no code-execution, takeover, email or payment tools.

Example client config

{
  "mcpServers": {
    "automatepal": {
      "type": "http",
      "url": "https://automatepal.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_TOKEN"
      }
    }
  }
}

Limits

  • 30 requests per minute per token, 64 KB per request, one JSON-RPC message per request (batches are refused).
  • Requests from a foreign browser Origin get 403. Missing or invalid tokens get 401.
  • Proposals: 10 per workspace per UTC day, 30 sources in total. A proposal stays unpublished until a manager approves it in Knowledge and then publishes it with consent.
  • Test questions: 20 per UTC day, not recorded in analytics. Source answers need the knowledge search provider configured.
  • Replies: only while the conversation is taken over and its link has not expired, 1,000 characters each, 100 messages per conversation. The ticket history records that a reply was sent via an MCP token, not the text. Nothing is emailed.
  • Settings changes: 20 per workspace per UTC day, validated like Widget studio (turning working hours on needs a time zone), audited.
  • One metadata row per tool call (tool and outcome, never arguments).

Limits and what is not built

  • Billing support, owner replies, working hours and the MCP server are built and tested locally. Their database migrations (044 to 047) are not yet applied to the hosted preview. The same goes for leads, the MCP reply and settings tools, the widget SDK and follow-up suggestions.
  • Only PayPal has been checked against a real sandbox account. The other providers are verified against their published contracts and local mocks, not real accounts.
  • Polar, Braintree and Cashfree adapters are not built, and no other provider is supported.
  • Payment execution is off everywhere. The bot cannot charge, capture or refund, and refund decisions are records only.
  • No email, Slack, WhatsApp or SMS delivery. Owner replies reach the visitor only inside the widget.
  • No external MCP client (for example a desktop assistant or an IDE) has been acceptance-tested yet.
  • No SOC 2, HIPAA or uptime SLA. See Security and Status.