Skip to main content
The probot-self-hosted widget only talks to the ProBot platform when you supply a dashboard.token. And even then, only two write-only endpoints under /api/v1/bot/*. Both are authenticated with the pbt_… bot token minted in your dashboard:
  • A missing or malformed header → 401 missing_bot_token.
  • An unknown, revoked, or expired token → 401 invalid_bot_token.
  • The token resolves to exactly one bot, so no botId is ever passed in a request body or path parameter.
This contract is pinned to v1. Breaking changes will ship as /api/v2 with a documented deprecation window, so a deployed widget or server-side client can rely on a stable shape.

Base URL

Production:
Point elsewhere by setting dashboard.apiUrl on <ProbotBot />, or by overriding your custom SDK’s base URL. Useful for staging mirrors or when running the platform locally for tests.

Endpoints

POST /api/v1/bot/conversations

Persists one chat session’s transcript so it appears in the owner’s dashboard. UPSERTs on (bot, sessionId), so the same sessionId sent twice coalesces into one conversation row and the message count increments. Request:
Success response (201 Created):
Failure responses: curl:
Side effects:
  • Emits a conversation_started notification (once, on first insert) visible in the owner’s dashboard bell.
  • Bumps the bot’s aggregate total_conversations and total_messages counters (surfaced on the dashboard overview).

POST /api/v1/bot/leads

Captures a recruiter lead. Idempotent on (bot, conversationId, email) - a duplicate submission returns 200 with deduped: true instead of creating a second row. Request:
Fresh capture response (201 Created):
Duplicate capture response (200 OK):
The lead.id in the deduped response is the ORIGINAL row’s id, not a newly-minted one. That lets a client optimistically build “leads I’ve touched” state without knowing whether the platform had the row before. Failure responses: curl:
Side effects:
  • Emits a lead_captured notification.
  • If the bot owner has notify_leads_email enabled, best-effort sends an email to their account address.

Rate limits

Both endpoints are rate-limited per bot via the same underlying rate limiter used for the managed /api/chat/[botId] path:
  • Default 10 requests / minute per bot.
  • Default 50 requests / day per bot.
  • Overrideable per-bot via the dashboard’s Bot Configuration → Advanced → Rate limits.
  • On rejection: 429 rate_limited with a Retry-After header.
The widget’s fire-and-forget calls swallow 429s silently - your local chat continues to work. If you’re POSTing from your own server-side integration and hitting 429s, either bump the per-bot limit in the dashboard or batch calls yourself.

What’s not exposed

Deliberately absent from this contract:
  • GET /config - self-hosted bots configure themselves in your codebase, so there is no platform-side config endpoint. The widget never reads config from us.
  • POST /knowledge - knowledge lives in your <ProbotBot /> props. No retrieval-as-a-service call.
  • PUT / PATCH / DELETE on conversations or leads - the contract is write-only. Data mutations happen through the owner’s dashboard, not the token surface.
This keeps the surface auditable: two endpoints, both write-only, both scoped to a single bot.

Debugging tips

Confirm your token works before wiring the widget:
If you get 401, the token is wrong or revoked. Double-check the dashboard’s Token list. Watch analytics land in real-time: register a bot, mint a token, then in one terminal send a conversation POST, and in another watch the dashboard - the row shows up within a couple of seconds.

Client SDK

If you’d rather not hand-roll the fetch calls, probot-self-hosted ships helpers:
Both helpers swallow failures and return null / false - matching the widget’s “analytics never breaks chat” contract. Wrap with your own try/catch if you want to surface failures to the caller.