Documentation
Add professional support to your website in under 2 minutes.
Quick start
The fastest way to get started is the JS widget. Paste this before your closing </body> tag:
<script
src="https://app.simplesupport.uk/widget/widget.js"
data-key="YOUR_API_KEY"></script>
Replace YOUR_API_KEY with the API key from your admin panel settings.
💡 Don't have an account? Create a free one — takes 30 seconds.
Create an account
Sign up at dashboard.simplesupport.uk. You'll get:
- Your API key (shown once — copy it)
- Access to the admin panel
- Free plan (100 tickets/month)
JS Widget
The widget adds a floating support button to your website. One line of code:
<script src="https://app.simplesupport.uk/widget/widget.js" data-key="YOUR_API_KEY"></script>
Options
<script
src="https://app.simplesupport.uk/widget/widget.js"
data-key="YOUR_API_KEY"
data-position="bottom-right"
data-lang="en"
data-color="#4F46E5"
></script>
Custom colors with CSS
Override the widget's CSS custom properties from your site's stylesheet:
.ss-w {
--ss-p: #your-color; /* primary color */
--ss-r: 8px; /* border radius */
--ss-f: system-ui; /* font family */
}
Logo & favicon (Pro, Business and Scale)
Upload-free branding: paste public URLs in Settings → Branding.
logo_url— shown at the top of the widget panel. PNG or SVG, recommended height 28px.favicon_url— used when the support form is embedded as a full page via iframe.
Both must be served over HTTPS. Leave blank to remove.
Content Security Policy (CSP)
If your site sends a Content-Security-Policy header, the browser will block widget.js unless you whitelist our domain. Add https://app.simplesupport.uk to the following directives:
script-src https://app.simplesupport.uk;
connect-src https://app.simplesupport.uk;
style-src https://app.simplesupport.uk 'unsafe-inline';
img-src https://app.simplesupport.uk data: https:;
script-src— loadswidget.js.connect-src— widget API calls (config, tickets, replies).style-src— loadswidget.cssplus a tiny inline style for your primary color (requires'unsafe-inline'or a nonce).img-src— your business logo (can be on any HTTPS CDN).
No frame-src, font-src or 'unsafe-eval' needed.
WordPress
Use the official plugin — the easiest way to add SimpleSupport to any WordPress site.
Plugin (recommended)
- The plugin is in review on the WordPress.org directory. Until it's published, install SimpleSupport using the universal JS widget (see JS Widget above) — paste one
<script>tag into your theme footer via Appearance → Theme File Editor or a code-snippets plugin. - Go to SimpleSupport → Settings and paste your API key (find it in Settings → Widget in your dashboard).
- The support widget appears on your site automatically. A live ticket badge shows up in the wp-admin menu.
Optional: uncheck Show support widget on all pages in Settings and use the shortcode [simplesupport] to embed the widget on a specific page only. You can also customise the widget position (bottom-right / bottom-left) and brand colour from the same Settings screen.
Manual (no plugin)
Add to your functions.php or use an "Insert Headers and Footers" plugin:
function simplesupport_widget() {
echo '<script src="https://app.simplesupport.uk/widget/widget.js" data-key="YOUR_API_KEY"></script>';
}
add_action('wp_footer', 'simplesupport_widget');
HTML Embed
Embed the support form inline on a page using an iframe:
<iframe
src="https://app.simplesupport.uk/embed/YOUR_API_KEY"
width="100%"
height="500"
frameborder="0"
title="Support"
></iframe>
Email Gateway
Available on Pro, Business and Scale. Customers open tickets by emailing support@yourcompany.com. Starter accounts can activate a one-time 14-day trial of this feature from Settings.
Setup
- Go to Settings → Email Gateway in your panel
- Add your support email address
- Add the MX record shown to your DNS
- Click "Verify" — takes up to 24h to propagate
REST API
Base URL: https://app.simplesupport.uk
All requests require: Authorization: Bearer YOUR_API_KEY
Create a ticket
POST /api/tickets
{
"customer_email": "user@example.com",
"customer_name": "Jane Smith",
"subject": "Cannot access my account",
"message": "I've tried resetting..."
}
List tickets
GET /api/tickets?status=open&limit=20
Reply to a ticket
POST /api/tickets/:id/messages
{ "body": "Hi Jane, let me help with that..." }
Update ticket status
PATCH /api/tickets/:id
{ "status": "resolved" }
Other fields you can patch: priority (low|medium|high), assigned_agent_id, and team_id (must belong to your tenant — pass null to unassign).
AI support agent (Pro, Business and Scale)
Our AI assistant answers tickets based on a knowledge document you provide. Two modes, switchable per site in Settings → AI responses:
- Draft mode (Pro and above) — the AI prepares a reply, you review/edit and click "Send to customer". Nothing leaves the panel without your approval.
- Auto mode (Business and Scale) — the AI sends the reply directly to the customer when the answer is in your knowledge doc. When it isn't, the ticket subject is tagged
[Needs review]and notifications go to your agents for manual handling.
Knowledge document size is tiered by plan:
- Pro: up to 2,000 characters (compact FAQ).
- Business and Scale: up to 7,000 characters (full playbook).
Paste your knowledge document with UPPERCASE section titles. The model is instructed to answer only from the document — if the answer isn't there, it stays silent and the ticket goes to manual review.
To prevent runaway auto-reply loops, after 2 AI replies already auto-sent on the same ticket, the next AI-generated message is held as a draft for an agent to approve.
Scale can also bring its own AI provider API key (Anthropic, OpenAI) from Settings → AI responses — usage is billed directly to your provider account and removes our monthly query cap.
Teams & departments (Pro, Business and Scale)
Group agents into departments and route tickets to the right one. Notifications go only to the assigned team's members. Limits: Pro up to 3 teams, Business up to 10, Scale unlimited.
When at least one team exists, the widget shows a "Choose a department…" dropdown automatically — no extra config. Customers can pick the team that should receive their ticket.
Team management endpoints are session-authenticated (panel) and require role = admin. They are not callable with the public API key — use the dashboard or your browser session cookie.
List teams
GET /api/admin/teams
→ { "data": [{ "id", "name", "member_count", "created_at" }] }
Create / rename / delete
POST /api/admin/teams { "name": "Sales" }
PATCH /api/admin/teams/:id { "name": "Billing" }
DELETE /api/admin/teams/:id
Deleting a team cascades its memberships and sets team_id = NULL on its tickets (no tickets are lost).
Manage members
GET /api/admin/teams/:id/agents
POST /api/admin/teams/:id/agents { "agent_id": "ag_..." }
DELETE /api/admin/teams/:id/agents/:agentId
Filter tickets by team
GET /api/admin/tickets?team=tm_xxx # tickets assigned to a team
GET /api/admin/tickets?team=none # tickets with no team assigned
Error codes
402 UPGRADE_REQUIRED— Starter plan trying to mutate teams.402 PLAN_LIMIT_REACHED— Pro plan creating a 4th team, or Business creating an 11th.403 FORBIDDEN— Logged in asagent, notadmin.409 CONFLICT— Team name already exists in this tenant.
Troubleshooting
Widget blocked by CSP and I can't edit server headers
If your browser console shows Failed to load <script> with source "https://app.simplesupport.uk/widget/widget.js" or a Content-Security-Policy violation, and you don't have access to the server config that sends the CSP header, work through these options in order:
-
Confirm the CSP actually comes from a header. Open DevTools → Network → click the page request → Response Headers. If you see
content-security-policy:there, it's server-sent. If you only see a<meta http-equiv="Content-Security-Policy">in the HTML, you can just edit that tag — meta CSP lives in the page source. -
Find who controls the header. Common locations, depending on your stack:
- Cloudflare → see the detailed Cloudflare guide below.
- Vercel / Netlify →
vercel.json,netlify.toml, or_headers. - Next.js / Nuxt / custom Node →
next.config.jsheaders(), middleware, or your reverse proxy. - Apache / Nginx →
.htaccessor theserver/locationblock. - WordPress with a security plugin (Wordfence, Really Simple SSL, iThemes) → the plugin's CSP/Security Headers section.
- Shopify / Wix / Squarespace / hosted SaaS → you typically can't change response headers. Skip to step 4.
- Ask the person who can. Most of the time the CSP was set by a developer or devops teammate, not the person installing the widget. Send them the CSP snippet above — the change is one line and reviewable in seconds.
-
If no server access is possible at all (locked-down hosted SaaS), the widget can't load — no third-party widget can bypass a server-sent CSP, it's a browser-enforced security feature. Workarounds:
- Use the HTML Embed iframe on a single "Contact" page instead of the floating widget. The iframe still requires
frame-src https://app.simplesupport.ukin the CSP, so this only helps ifframe-srcis already permissive (*orhttps:). - Use the Email Gateway (Pro and Business plans). Customers email
support@yourcompany.com— no JavaScript, no CSP impact at all. - Link to a hosted support page:
https://app.simplesupport.uk/embed/YOUR_API_KEYopens in a new tab with no embedding required.
- Use the HTML Embed iframe on a single "Contact" page instead of the floating widget. The iframe still requires
Editing CSP on Cloudflare (step by step)
Cloudflare can set the CSP header in three different places depending on how your site is deployed. Figure out which one applies first:
- Cloudflare Pages — static/Jamstack sites deployed from a Git repo. Fix it in a
_headersfile. - Cloudflare Workers — the CSP is set in JS code. Edit the Worker source.
- Cloudflare as a proxy (orange cloud in front of any origin) — the CSP either comes from your origin server, or from a Cloudflare Transform Rule that rewrites headers.
To tell which one you have: in the Cloudflare dashboard, look at the left sidebar. If you see Workers & Pages and your project is listed under Pages, you're on Pages. If it's under Workers, it's a Worker. Otherwise it's a proxied zone.
Option A — Cloudflare Pages (_headers file)
- Open the Git repository connected to your Pages project.
- At the root of the published output (usually the repo root, or
public/,dist/,out/depending on framework), open or create a file called_headers(no extension, leading underscore). - Add (or edit) a block like this:
The/* Content-Security-Policy: script-src 'self' 'unsafe-inline' https://app.simplesupport.uk; connect-src 'self' https://app.simplesupport.uk; style-src 'self' 'unsafe-inline' https://app.simplesupport.uk; img-src 'self' data: https:;/*means "apply to all paths". Keep any existing directives you already had — just addhttps://app.simplesupport.uktoscript-src,connect-src, andstyle-src. - Commit and push. Pages will redeploy automatically.
- Verify with DevTools → Network → reload page → click the HTML request → Response Headers → confirm
content-security-policynow includes our domain.
Option B — Cloudflare Worker
- Dashboard → Workers & Pages → click your Worker → Edit code (or edit the repo /
wrangler.tomlproject locally). - Find where
Content-Security-Policyis set. It'll look something likeresponse.headers.set("Content-Security-Policy", "…")or be inside aheadersobject. - Add
https://app.simplesupport.uktoscript-src,connect-src, andstyle-src. Save and deploy.
Option C — Cloudflare proxy (Transform Rule)
Use this if the CSP header is already being added by Cloudflare itself (not your origin), or if you want to override what your origin sends. This is the typical case for sites whose content-security-policy response header is set at the edge.
Step 1 — Copy your current CSP first. "Set static" replaces the whole header, so if you paste only the new bits, you will lose everything you already had. Before touching anything in Cloudflare:
- Open your site in the browser → DevTools (F12) → Network tab → reload the page.
- Click the first request (the HTML document, usually your domain name).
- In the right panel, open Response Headers and find
content-security-policy. Copy its full value to a text editor.
Step 2 — Add our domain to the copied value. In the copied string, locate each of these three directives and append https://app.simplesupport.uk at the end of each (before the semicolon that separates it from the next directive):
script-srcstyle-src— if it doesn't exist yet, add a whole new directive:style-src 'self' 'unsafe-inline' https://app.simplesupport.uk;connect-src— same: add it if missing.
Example of what the final string looks like (directives separated by ;, everything on one line — no quotes around the whole value):
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cloud.umami.is https://cdn.jsdelivr.net https://app.simplesupport.uk; img-src 'self' data: https:; style-src 'self' 'unsafe-inline' https://app.simplesupport.uk; font-src 'self' data:; connect-src 'self' https://cloud.umami.is https://api-gateway.umami.dev https://app.simplesupport.uk
Step 3 — Create the Transform Rule in Cloudflare.
- In the Cloudflare dashboard, click your domain from the home page (not "Workers & Pages" — click the domain itself).
- Left sidebar → Rules → Overview (on older UIs: Rules → Transform Rules).
- Open the Modify Response Header tab (also labelled "HTTP Response Header Modification" in some accounts).
- If a rule for
Content-Security-Policyalready exists, click it to edit; otherwise click Create rule. You will land on a form titled "Edit/Create HTTP Response Header Transform Rule". Fill it in like this:- Rule name (required) → anything descriptive, e.g.
CSP with SimpleSupport. - If incoming requests match → select the radio All incoming requests.
- Under Then... Modify response header there is a row with four fields. Set them exactly:
- First dropdown → Set static.
- Header name →
Content-Security-Policy(exact casing doesn't matter, but no extra spaces). - Value → paste the full string from Step 2. No surrounding quotes. Do not wrap it in
"..."— the=symbol next to the field is just a visual separator, not "this is an expression".
- Place at → First (so it overrides any CSP from the origin).
- Rule name (required) → anything descriptive, e.g.
- Click Save (blue button, bottom right). Changes are live in seconds.
Step 4 — Verify. Back in the browser: DevTools → Network → tick Disable cache → hard-reload the page → click the HTML request → Response Headers. Confirm:
content-security-policyappears only once and containshttps://app.simplesupport.uk. If it appears twice, the origin is also sending one — change your Transform Rule's operation to Set static (not "Add") and redeploy.- Console shows no CSP violations when the widget loads.
Common mistakes:
- Pasting the value with double quotes → header becomes invalid and Cloudflare silently falls back to the origin's CSP.
- Pasting only the new bits (
script-src https://app.simplesupport.uk) → you lose every other directive and likely break other integrations. Always paste the full CSP. - Forgetting to click Save (rules remain as drafts until saved/deployed).
- Can't find "Transform Rules"? Requires the domain to be proxied through Cloudflare (orange cloud). If DNS-only (grey cloud), Cloudflare isn't touching the response — the CSP comes from your origin, and you must change it there.
Widget installed but button doesn't appear
- Check the browser console for errors (CSP, CORS, 401/403). A 401 usually means the API key is wrong or disabled.
- Verify the Authorized domain in Settings → Integration matches the site where you pasted the snippet (no trailing slash, no
https://). - If you run an ad blocker or a privacy extension, disable it to confirm it isn't blocking the script.
Still stuck? with your site URL and a screenshot of the browser console.