Send Paywall Shown Event
POST https://api.botsi.com/v2/eventsCall this immediately after the Paywall is displayed. The impression is what conversion is measured against, and what lets the model learn from the outcome.
Impressions are not deduplicated. Sending the same event twice for one paywallSessionId records two impressions, so send it once per Paywall view.
Request body#
The body is a single JSON object, and these two fields are the entire accepted field set.
Everything else about the event — Paywall, Placement, A/B test, AI Pricing Model, and the Profile itself — is derived server-side from the token.
Send an object, not an array
A JSON array is v1's shape, and v2 rejects it with 400 Request body must be a single event object, not an array.
Any field beyond the two above is rejected rather than ignored. Sending profileId or customerUserId returns a 400 naming the field: the signed token is the single source of identity, so a client value that disagrees with it is an error worth being told about instead of being silently overridden.
curl -X POST "https://api.botsi.com/v2/events" \
-H "Authorization: $BOTSI_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"eventType": "paywall_shown",
"paywallSessionId": "v1.eyJhIjo0MDIxLCJ3Ijo5MDUsInAiOiJvbmJvYXJkaW5nIiwiaSI6MTc4NTMxMjAwMH0.QmzR1w"
}'Working with the token#
Every Fetch Paywall response includes a unique paywallSessionId for the API response.
- Size. Roughly 200 characters today, no fixed maximum. Use
TEXTorVARCHAR(512). - One token per Paywall fetch.
Views expire after 24 hours. Transactions do not.
A paywall_shown event is accepted for 24 hours after the fetch that minted the token. Send it later and the request is rejected. Fetch a new Paywall before reporting the view.
Errors#
Every rejection is a 400 with code set to bad_request, and nothing is stored.
Response#
{ "ok": true }