Skip to content

Search the documentation by title, section, or page text.

AI Pricing Model API

Once your Pricing Model is set up and configured, the next step is to integrate your application with the Botsi API.

Before integrating with the API, be sure to follow the AI Pricing Model Setup, which establishes important components that are referenced in the sections below.

The API call sequence at a glance#

  1. Create a Profile for each user.
  2. Publish custom attributes on that Profile, if you have additional user metadata.
  3. Fetch the Paywall and persist the paywallSessionId it returns.
  4. Send a paywall_shown event, with the paywallSessionId.
  5. Validate purchases if using IAP with App Store or Google Play.

Authenticating#

Every endpoint takes the same two headers. The secret key is on your app's configuration page in the dashboard at https://app.botsi.com.

Authorization: {{SECRET_KEY}}
Content-Type: application/json

Creating a Profile#

curl -X POST https://api.botsi.com/v2/profiles \
  -H "Authorization: $BOTSI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "country": "US",
    "device": "iPhone 15",
    "os": "iOS 15.0.2",
    "platform": "ios",
    "appVersion": "2.3.4",
    "appUserId": "user-123"
  }'

Store the profileId from the response.

Full request and response details here: Create a Profile.

Enrich with custom attributes#

Custom attributes attach additional metadata to a Profile: user level, subscription type, referral source. Optional but recommended for enriching profile data, which helps the pricing model through learning phases.

OperationEndpointReference
Add one or more attributesPOST /v2/custom-attributesAdd Custom Attributes
Update one or more attributesPUT /v2/custom-attributesUpdate Custom Attributes

Fetching a Paywall#

Call this any time after the Profile exists, for the Placement the user is about to reach.

curl -X POST https://api.botsi.com/v2/paywall \
  -H "Authorization: $BOTSI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "placementId": "ai-placement-id",
    "profileId": "0072102a-c00c-4ea5-9271-1b6e975f2d63"
  }'

Each product in data.paywallProducts comes back with its identity on every configured store in a nested block (appStore, playStore, stripe, web2wave, custom), each null where the product is not sold, so one call covers whichever platform the user is buying through.

Full request and response details here: Fetch Paywall.

Reporting that the Paywall was shown#

Send the paywall_shown event after the Paywall is displayed to a user on screen. Impressions are not deduplicated, so send it once per Paywall view: a repeated event for the same paywallSessionId records a second impression.

The body is a single object carrying only these two fields. A JSON array is v1's shape and is rejected, as is any extra field — the token already identifies the Profile, Paywall, Placement, and model.

{
  "eventType": "paywall_shown",
  "paywallSessionId": "v1.eyJhIjo0MDIxLCJ3Ijo5MDUsInAiOiJvbmJvYXJkaW5nIiwiaSI6MTc4NTMxMjAwMH0.QmzR1w"
}

A token that fails its signature check, or that was issued for a different app, returns 400 and stores nothing. A paywall_shown sent more than 24 hours after the fetch that minted the token is rejected the same way, so fetch a fresh Paywall before reporting the view.

Validating an IAP purchase#

Call store-specific validation endpoints to validate purchases once complete.

Apple App Store#

POST /v2/purchases/apple-store/validate takes transactionId and originalTransactionId from the StoreKit payment object, the productId, the Placement and attribution fields, and environment set to production or sandbox.

Under StoreKit, transactionId and originalTransactionId come from SKPaymentTransaction, and the Product identifier from SKPaymentTransaction.payment.productIdentifier. Under StoreKit 2, all three come from the Transaction object.

curl -X POST https://api.botsi.com/v2/purchases/apple-store/validate \
  -H "Authorization: $BOTSI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "placementId": "ai-placement-id",
    "paywallId": 42,
    "source": "purchasing",
    "productId": "premium_annual",
    "isSubscription": true,
    "originalTransactionId": "2000000261699248",
    "environment": "sandbox",
    "transactionId": "2000000871590381",
    "profileId": "fff3c120-0ca8-480f-9b19-3955a5428e39",
    "isExperiment": true,
    "aiPricingModelId": 32
  }'

A successful validation returns the updated Profile, including its Access Levels, subscriptions, and total revenue. Read state and accessLevels to decide what the user now has access to.

{
  "ok": true,
  "data": {
    "profileId": "fff3c120-0ca8-480f-9b19-3955a5428e39",
    "appUserId": "user-123",
    "state": "subscribed",
    "totalRevenueUsd": 49.99,
    "accessLevels": {},
    "subscriptions": {},
    "nonSubscriptions": {}
  }
}

Full field list: Validate Apple Store Purchase.

Google Play#

POST /v2/purchases/play-store/validate takes the purchase token, the productId, the Placement and attribution fields, environment, and one of two offer objects.

Send subscriptionOfferDetails for a subscription or oneTimePurchaseOfferDetails for a one-time purchase. One or the other, never both.

curl -X POST https://api.botsi.com/v2/purchases/play-store/validate \
  -H "Authorization: $BOTSI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "token": "algojlnkodhhjceoicbpjngh.AO-J1Owvcga8j2uUoKEpn5AnvpSFr8dxEFm0c6qk5",
    "placementId": "fresh_placement",
    "productId": "monthly",
    "paywallId": 569,
    "isExperiment": true,
    "aiPricingModelId": 32,
    "environment": "production",
    "profileId": "55bbd5f3-6de8-4d3b-8a55-006e6af6e3dd",
    "subscriptionOfferDetails": {
      "basePlanId": "1month-sub",
      "pricingPhases": [
        {
          "priceAmountMicros": 359990000,
          "currencyCode": "UAH",
          "billingPeriod": "P1M",
          "recurrenceMode": 1,
          "billingCycleCount": 0
        }
      ]
    }
  }'

The response is the same shape Apple returns, so a single handler can process either store.

{
  "ok": true,
  "data": {
    "profileId": "55bbd5f3-6de8-4d3b-8a55-006e6af6e3dd",
    "appUserId": "user-123",
    "state": "subscribed",
    "totalRevenueUsd": 8.72,
    "accessLevels": {},
    "subscriptions": {},
    "nonSubscriptions": {}
  }
}

Full field list, including pricingPhases and a one-time purchase sample: Validate Google Play Store Purchase.