Connect
Custom REST tools
Give your AI assistant a brand-new skill by pointing it at any HTTP endpoint — your database, your CRM, a SaaS API, an internal service. No code. Describe what you want and let Create with AI draft it, or fill in seven fields yourself. This is the same mechanism that powers our own dashboard assistant’s abilities.
Custom REST tools require the Scale plan plus the Custom Tools add-on. Find them under Integrations → Custom REST.
How a tool works
A custom tool is one HTTP request the assistant can make on its own. When the conversation calls for it, the model collects the inputs you defined, the platform fills them into the request, calls your endpoint, and hands the response back to the model to use in its reply.
- You define a tool: a name, a description (so the model knows when to use it), the HTTP request, and the inputs to collect.
- A visitor says something that needs it (“where’s my order?”).
- The model gathers the inputs, the platform makes the call, and the model answers with the live result.
Create with AI
The fastest way to build one. In Integrations → Custom REST → Add custom tool, use the Create with AI box at the top: describe what you want in plain English and which service to connect, and the assistant drafts every field below using its knowledge of well-known APIs.
Try a prompt like:
Create a Jira issue in our SUPPORT project
Look up a shipment by tracking number in our Postgres orders table
It fills in the method, endpoint, input schema, headers, and body for you. You then review and finish — usually just pasting your real API token where it left a placeholder (it never invents secrets). The exact same fields are explained below, in case you prefer to build by hand or tweak the draft.
It also knows Quincer’s own API, so prompts like
“create a tool that builds a new Quincer persona” or “let the
assistant list my leads” produce the real endpoint and the correct
Bearer cw_dev_ developer-key auth automatically.
The fields
| Field | What it is |
|---|---|
| Name | The tool name the model calls, e.g. track_shipment. Letters, digits, underscores; starts with a letter. |
| Method | GET, POST, PUT, PATCH, or DELETE. |
| Description | What the model reads to decide when to call the tool. Be specific and action-oriented, and mention the inputs. |
| Endpoint | The full https:// URL. Drop collected values into the path or query with {{input.field}}. |
| Input schema | A JSON Schema describing the inputs the model should collect. Each property gets a description; list the truly required ones in required. |
| Headers | A JSON object of headers (auth, content type). Paste your real secrets here. |
| Body template | For POST/PUT/PATCH: the request body as JSON, with {{input.field}} placeholders. Leave blank for GET/DELETE. |
| Response JSONPath (optional) | A dot-path into the JSON response (e.g. data.status) to return just that part to the model. Leave blank to return the whole response. |
| Require verified visitor (optional) | Only let the tool run for a signed-in visitor, and inject their identity (see placeholders below). |
Placeholders
Use these in the endpoint URL and body template — substitution is deep (works inside nested JSON):
{{input.field}}— the value the model collected for that input.{{identity.sub}}— the verified visitor’s user id (requires Visitor sign-in + “require verified visitor”).{{identity.email}}/{{identity.<claim>}}— any claim from the verified token.{{identity.jwt}}— the raw verified JWT, to forward auth to a backend that re-verifies it.
Example 1 — create an AI persona
Teach the assistant to spin up new personas on command, using Quincer’s own
REST API. First create a key under Integrations → API keys
with the personas:write scope, then:
| Name | create_persona |
| Method | POST |
| Description | Create a new AI persona for this brand. Use when the operator asks to add or create a persona. Inputs: name and prompt. |
| Endpoint | https://chat.quincer.com/api/v1/personas |
Input schema
{
"type": "object",
"properties": {
"name": { "type": "string", "description": "The new persona's name" },
"prompt": { "type": "string", "description": "The persona's system prompt" }
},
"required": ["name", "prompt"]
}
Headers — the Quincer API uses a Bearer token (your key starts with cw_dev_):
{ "Authorization": "Bearer cw_dev_YOUR_KEY", "Content-Type": "application/json" }
Body template
{ "name": "{{input.name}}", "systemPrompt": "{{input.prompt}}" }
Now say “create a persona called Spanish Support that always replies in Spanish” and it appears under Personas.
Example 2 — look up a shipment in Postgres
Expose a read-only query over a Postgres table via a REST layer like
PostgREST or
Supabase. This one is a GET, so there’s no body.
| Name | lookup_shipment |
| Method | GET |
| Description | Look up a shipment by its tracking number. Returns the current status, carrier, and ETA. Use when a visitor asks where their order is. |
| Endpoint | https://YOUR-PROJECT.supabase.co/rest/v1/shipments?tracking_number=eq.{{input.tracking_number}}&select=status,carrier,eta |
Input schema
{
"type": "object",
"properties": {
"tracking_number": { "type": "string", "description": "The shipment's tracking number" }
},
"required": ["tracking_number"]
}
Headers
{
"apikey": "YOUR_SUPABASE_ANON_KEY",
"Authorization": "Bearer YOUR_SUPABASE_ANON_KEY"
}
Tip: a REST layer returns an array of rows; set
Response JSONPath to 0 to hand the model just the
first match. Keep the role/key read-only and scoped with row-level security so
the tool can only see what you intend.
Example 3 — open a Jira support ticket
Let the assistant file a Jira issue when it can’t resolve something. Auth is
HTTP Basic with your Atlassian email + an
API token,
base64-encoded as email:token.
| Name | create_jira_issue |
| Method | POST |
| Description | Open a Jira issue in the SUPPORT project. Use when the visitor reports a problem you can't resolve. Inputs: summary and description. |
| Endpoint | https://YOUR-DOMAIN.atlassian.net/rest/api/3/issue |
Input schema
{
"type": "object",
"properties": {
"summary": { "type": "string", "description": "Short issue title" },
"description": { "type": "string", "description": "What the visitor reported" }
},
"required": ["summary", "description"]
}
Headers
{
"Authorization": "Basic YOUR_BASE64_EMAIL_AND_TOKEN",
"Content-Type": "application/json"
}
Body template
{
"fields": {
"project": { "key": "SUPPORT" },
"issuetype": { "name": "Task" },
"summary": "{{input.summary}}",
"description": {
"type": "doc", "version": 1,
"content": [{ "type": "paragraph", "content": [
{ "type": "text", "text": "{{input.description}}" }
]}]
}
}
}
(Jira’s description uses Atlassian Document Format, hence the
nested shape. Create with AI writes this for you if you’d
rather not hand-roll it.)
Test it
- Save the tool. It appears in the Custom REST list, toggle Enabled.
- Open your widget (or the preview) and ask something that should trigger it.
- Watch the model collect the inputs, call your endpoint, and answer with the live result.
If it doesn’t fire, tighten the Description so it’s unmistakable when the tool applies, and double-check required inputs.
Security & limits
- Your secrets stay in headers — paste real tokens there; the assistant never sees or speaks them.
- Public endpoints only — the endpoint must resolve to a public address; requests to private/internal IPs are blocked.
- Per-tool timeout & rate limit keep a slow or chatty endpoint from affecting conversations.
- Scope down — give the tool the narrowest credential that works (read-only key, single project, row-level security). The assistant can only do what the endpoint allows.
- Require verified visitor for any per-user action, and use
{{identity.*}}so a visitor can only act on their own data.