Authentication
API keys
Create keys under Settings → API Keys. A key looks like wpai_<prefix>.<secret> and the full value is returned exactly once, at creation. We store only a hash, so a lost key cannot be recovered — revoke it and make another.
Keys authenticate an organization, never a person. Every query they make is scoped to that organization, which is what makes a leaked key a tenant-level problem rather than a platform-level one.
Presenting a key
The public widget surface accepts a key four ways, in this order of precedence. The private API accepts only the header.
| How | Example | Private API |
|---|---|---|
| Header | X-API-Key: wpai_abc.def | Yes |
| Bearer | Authorization: Bearer wpai_abc.def | No |
| Body field | { "apiKey": "wpai_abc.def" } | No |
| Query param | ?apiKey=wpai_abc.def | No |
curl https://api.wpai.co.in/api/templates \
-H "X-API-Key: wpai_abc123.def456..."Avoid the query parameter
X-API-Key everywhere you can.Scopes
A key created without any scopes is a legacy key and keeps full access. Anything you create today should name its scopes.
| Scope | Grants |
|---|---|
chat:write | Send a message to the assistant from a website widget, and reset a session. |
chat:read | Read back one widget session’s conversation. |
bookings:read | List bookable slots for a date. |
bookings:write | Create a booking from a website form. |
messages:send | Server-to-server access. See the warning below: this reaches the whole API. |
A request missing a required scope returns 403 naming what was missing: API key is missing required scope: bookings:write.
Widget keys vs server keys
There are two authentication paths and the difference matters more than it looks. Scopes are checked on /api/public/*. Everywhere else, a valid key simply authenticates as an organization administrator.
A widget key is publishable
A key holding only widget scopes — chat:write, chat:read, bookings:read, bookings:write — is designed to ship in the page source of your own website. Present it on the private API and it is refused:
{
"error": "This key is scoped to the website widget and can only be used on /api/public. Create a key with the messages:send scope for server-to-server calls."
}A server key is an admin key
A key holding messages:send is not restricted to sending. On the private API it authenticates as an organization administrator — treat it with the same care as the password to your WpAi account, and keep it on your server.
Never mix the two on one key
chat:write and messages:send is not widget-only, so it is accepted on the private API. Publishing such a key in your website's JavaScript publishes organization-admin access. Keep the widget key and the server key separate.Limits and revocation
- An organization may hold 10 active keys. Creating an eleventh returns
403 Maximum 10 active API keys. - Deleting a key is a soft revoke — it stops working immediately and stays listed with a revocation date, so an audit can still see it existed.
- Keys record a
lastUsedAtstamp. It is best-effort and never fails a request, so treat it as a hint rather than an audit trail. - Creating and revoking keys requires an organization administrator and the
api_accessplan feature. - Requests are rate limited to 300 per minute overall. A handful of heavier calls — uploads, imports and exports — allow 20 per minute. Over either, you get
429 Too many requests, slow down.