Get Paywall

POSThttps://app.botsi.com/api/v1/web-api/paywalls

After a profile has been created, call Get Paywall at any time to retrieve the paywall variant that Botsi’s AI Pricing model selected for this user. The response identifies which of your pre-configured paywall variants to display, it is not a price feed. No field in this response contains a price: the prices and product IDs for each variant are fixed in advance, in the Botsi dashboard and in your own app code or paywall tool, and your app maps the returned identifier to the matching variant.

Botsi selects a variant, it does not set prices

AI Pricing Model: a model that selects which of your pre-configured paywall variants to show each user. It does not set prices.

Holding the prices and product IDs for each variant as constants in your client is the expected integration pattern, not a mistake. See the AI Pricing Models overview for the full selection flow.

Follow the notes below for a successful request:
  • You must identify the user by providing either profileId or customerUserId, and specify the placementId configured on the Botsi dashboard.

  • If optional fields are omitted when sending the request, Botsi will automatically fall back to the values stored on the user profile.

    Performance and timing

    The Get Paywall API uses AI models to determine the best paywall for a user, which introduces specific latency considerations. You must implement this endpoint strategically to ensure a seamless experience within your application.

    The response typically takes about 40 ms but can take up to 2 seconds depending on the AI prediction speed. To maintain a smooth user interface, follow these implementation guidelines:

    • Avoid calling this endpoint synchronously at render time.

    • Trigger the request early in the user journey, such as immediately after a profile is created.

    • Ensure the response is received and cached before the user reaches the point where the paywall must be displayed.

Request Body

application/json

ParameterTypeRequiredDescription
profileIdstringOptionalBotsi profile ID returned by Create Profile. Provide either profileId or customerUserId
customerUserIdstringRecommendedYour internal user ID. Provide either profileId or customerUserId
placementIdstringRequiredPlacement ID configured in Botsi dashboard
storestringRequiredStore serving the purchase: app_store, play_store, stripe, web2wave, or custom
localestringOptionalFalls back to profile value if omitted
countrystringOptionalFalls back to profile value if omitted
ipstringOptionalFalls back to profile value if omitted
storeCountrystringOptionalFalls back to profile value if omitted

Example Request

{
  "profileId": "0072102a-c00c-4ea5-9271-1b6e975f2d63",
  "placementId": "ai-placement-id",
  "store": "app_store"
}

cURL Example

curl -X POST "https://app.botsi.com/api/v1/web-api/paywalls"      -H "Authorization: {{secret_key}}"      -H "Content-Type: application/json"      -d ‘{
       "profileId": "0072102a-c00c-4ea5-9271-1b6e975f2d63",
       "placementId": "ai-placement-id",
       "store": "app_store"
     }’

Response

200Paywall retrieved

A successful request returns the selected paywall and metadata indicating whether it was served by the AI Pricing model.

Key properties you may want to store or forward to later steps include:

  • data.id - The internal paywall ID in Botsi.

  • data.externalId - The external paywall ID used in your app and the AI Pricing model. This identifies the selected variant, it is not a price: your app maps this value to the fixed prices and product IDs you configured in advance for that variant, in your own code or paywall tool. It can be added manually when configuring the Paywall in Botsi.

  • data.isExperiment - A boolean that indicates if the paywall was returned by the AI Pricing model.

  • data.aiPricingModelId - The ID of the AI Pricing model that served the paywall.

  • data.sourceProducts - The store product identifiers configured for the selected variant. These are identifiers, not prices. Each product's price is the one you set in App Store Connect or Google Play Console, and is read at runtime from the store SDK or from your own configuration.

  • data.paywallSessionId - An opaque attribution token for this paywall answer. Store it and echo it back on the paywall_shown event. It is returned on every answer kind — A/B, AI Pricing, and plain — so you do not need to branch on which identity fields came back.

Store the paywall session token

Store data.paywallSessionId against the user and return it byte for byte on the paywall_shown event. Botsi then fills in paywallId, placementId, abTestId, aiPricingModelId and isExperiment from the decision it recorded when it served this paywall, so those fields do not have to be reassembled on your side.

Treat the value as opaque: do not parse, decode, truncate, or construct it. It is roughly 200 characters today with no fixed maximum, so store it in a TEXT or VARCHAR(512) column rather than a narrow one.

Purchase validation is unchanged. Validate Apple Purchase and Validate Google Purchase do not accept paywallSessionId; keep sending paywallId, isExperiment and aiPricingModelId on those calls as you do today.

{
  "ok": true,
  "data": {
    "id": 42,
    "externalId": "paywall_premium_v2",
    "name": "Premium Paywall",
    "isExperiment": true,
    "aiPricingModelId": 32,
    "paywallSessionId": "v1.eyJhIjo0MDIxLCJ3Ijo5MDUsInAiOiJvbmJvYXJkaW5nIiwiaSI6MTc4NTMxMjAwMH0.QmzR1w",
    "sourceProducts": [
      {
        "productId": "premium_monthly",
        "basePlanId": "monthly-base",
        "offerId": "intro-offer-7d",
        "promotionalOfferId": null,
        "discountId": null
      }
    ]
  }
}

An A/B answer carries abTestId and abTestName instead of aiPricingModelId, and a plain answer carries neither. paywallSessionId is present in all three cases.

Try It Out

https://app.botsi.com/api/v1/web-api
Response
Click "Send API Request" to see the response here.