Build on PlainAnswer
A simple REST API for your agent: ask it questions, pull the leads it captures, and manage FAQs from your own code. Available on the Business plan.
What you can build
PlainAnswer's agent already answers your visitors, captures leads, and learns your content. The API and webhooks open that up to your own systems:
The moment a visitor leaves their name, email or phone, a signed webhook pushes the lead, with the question they asked, into your CRM, a spreadsheet, Slack, or anything with a URL. No inbox checking, no polling.
webhook: lead.capturedPut the same brain that answers on your website inside your own app, an internal staff tool, or a kiosk. Ask a question, get the answer with its sources, grounded only in your content.
POST /askIf your prices or policies live in another system, update FAQs programmatically whenever they change, so the agent never gives yesterday's answer.
POST /faqsWhen the agent hands a conversation to a human, get an event you can turn into a ticket, an alert, or an on-call ping, while the visitor is still on the site.
webhook: conversation.escalatedEverything below gets you from zero to a working call in a few minutes. For agencies and freelancers building on client sites, this pairs well with the Partner Program.
1. Get a key
In your dashboard, open the API tab and create a key. It is shown once, so copy it somewhere safe. Keys look like pa_live_... and can be revoked at any time.
2. Authenticate
Send the key on every request as a bearer token:
Authorization: Bearer pa_live_your_key_here
The quickest smoke test is /me, which returns your account and usage:
curl https://plainanswer.co.uk/api/v1/me \
-H "Authorization: Bearer pa_live_your_key_here"
3. Ask your agent
The same answering pipeline as your website widget: answers come only from your own content, with sources. Pass back conversation_id to continue a conversation.
curl -X POST https://plainanswer.co.uk/api/v1/ask \
-H "Authorization: Bearer pa_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"question": "What are your opening hours?"}'
Calls to /ask count toward your plan's monthly conversation allowance, exactly like widget conversations.
4. Pull your leads
Every visitor who left contact details, newest first, ready to sync into your CRM or spreadsheet:
curl "https://plainanswer.co.uk/api/v1/leads?limit=50" \
-H "Authorization: Bearer pa_live_your_key_here"
5. Manage FAQs
FAQs take priority over website content, so this is the way to teach your agent an exact answer programmatically:
curl -X POST https://plainanswer.co.uk/api/v1/faqs \
-H "Authorization: Bearer pa_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"question": "Do you deliver?", "answer": "Yes, next day across the UK."}'
Conversations are available too: GET /api/v1/conversations lists them and GET /api/v1/conversations/{id} returns a full transcript. The interactive reference covers every endpoint and field.
6. Webhooks: push, not poll
Instead of polling for new leads, set a webhook in your dashboard's API tab and PlainAnswer will POST to your URL the moment something happens:
lead.captured: a visitor left their name, email or phone. The payload carries the contact details, their question, the conversation id, and the reception note: akind(booking, quote, coverage, eligibility, hours), a short receptionist-stylesummary, and any extrafieldsthe visitor gave (preferred time, postcode). The agent never invents times, prices or availability; when the answer lives in the diary, not on the website, it takes a proper note instead.conversation.escalated: the agent handed a conversation to you.webhook.test: fired by the dashboard's "Send test" button.
Every delivery is signed. The X-PlainAnswer-Signature header is sha256= followed by an HMAC-SHA256 of the raw request body, keyed with your signing secret. Verify it before trusting the payload:
# Python
import hmac, hashlib
def verify(secret: str, body: bytes, signature_header: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header)
Respond with any 2xx status within a few seconds. Failed deliveries are retried twice, then dropped; your dashboard shows the last delivery status.
Limits and good behaviour
- 60 requests a minute per account.
/askis metered against your plan's conversation allowance; reads are not metered.- Keys are hashed at rest and shown only once. Revoking a key takes effect immediately.