Custom Web API Integration
Integrate Botsi AI Pricing directly into your web applications, landing pages, and web funnels using our REST API. This approach is ideal for web-based subscription flows, custom payment pages, and web-to-app user acquisition funnels where you need maximum flexibility in pricing presentation.
When to Use
Use the Custom Web API integration for:
- Web checkout pages and subscription flows
- Custom landing pages with pricing optimization
- Web-based payment pages
- Web funnels that drive mobile app signups
- SaaS applications with web-first onboarding
- Any scenario where you need direct API control over pricing selection
Prerequisites
- Active Botsi account
- API key from your Botsi dashboard
- Basic understanding of REST APIs and HTTP requests
Integration Steps
Step 1: Create a Profile (Server-Side)
Create a new user profile in Botsi. This should be done on your server to keep your API key secure.
const response = await fetch('https://api.botsi.com/api/v1/web-api/profiles', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'YOUR_API_KEY'
},
body: JSON.stringify({
// Optional: pass any known user data
customAttributes: {
email: user.email,
source: 'web_funnel'
}
})
});
const { data } = await response.json();
const profileId = data.profileId;
Step 2: Get Paywall Prediction
Fetch the AI-optimized paywall configuration for your user. The response includes the externalID that determines which pricing variant to display.
const paywallResponse = await fetch(`https://api.botsi.com/api/v1/web-api/profiles/${profileId}/get-paywall`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'YOUR_API_KEY'
}
});
const paywall = await paywallResponse.json();
// paywall.data.externalID — use to determine which pricing to show
// paywall.data.id — numeric ID for impression tracking
Step 3: Display Pricing on Your Web Page
Use the externalID from the paywall response to determine which pricing variant to show to the user. You control the UI completely and can display pricing in any format that fits your design.
Step 4: Send Impression Event
When the user sees the paywall, send an impression event to Botsi for analytics and model training.
await fetch(`https://api.botsi.com/api/v1/web-api/profiles/${profileId}/events`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'YOUR_API_KEY'
},
body: JSON.stringify({
paywallId: paywall.data.id, // Use numeric id, not externalID
event: 'paywall_impression'
})
});
Step 5: After Purchase — Validate with Botsi
After the user completes a purchase through your payment processor, validate the transaction with Botsi. This helps Botsi learn from successful conversions and improve pricing predictions.
For Stripe
POST /api/v1/web-api/purchases/stripe/validate
For Apple
POST /api/v1/web-api/purchases/apple-store/validate
For Google
POST /api/v1/web-api/purchases/play-store/validate
Complete End-to-End Example
Here's a full example showing the complete integration flow:
// Configuration
const BOTSI_API_KEY = process.env.BOTSI_API_KEY;
const BOTSI_BASE_URL = 'https://api.botsi.com/api/v1/web-api';
// 1. Create profile when user arrives at checkout
async function initializeCheckout(userEmail) {
try {
const response = await fetch(`${BOTSI_BASE_URL}/profiles`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': BOTSI_API_KEY
},
body: JSON.stringify({
customAttributes: {
email: userEmail,
source: 'web_checkout',
timestamp: new Date().toISOString()
}
})
});
const { data } = await response.json();
return data.profileId;
} catch (error) {
console.error('Failed to create Botsi profile:', error);
throw error;
}
}
// 2. Get optimized pricing
async function getPricingVariant(profileId) {
try {
const response = await fetch(`${BOTSI_BASE_URL}/profiles/${profileId}/get-paywall`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': BOTSI_API_KEY
}
});
const { data } = await response.json();
return {
paywallId: data.id,
variant: data.externalID,
price: getPriceForVariant(data.externalID)
};
} catch (error) {
console.error('Failed to get paywall:', error);
// Fallback to default pricing
return {
paywallId: null,
variant: 'default',
price: 9.99
};
}
}
// 3. Track impression
async function trackPaywallImpression(profileId, paywallId) {
try {
await fetch(`${BOTSI_BASE_URL}/profiles/${profileId}/events`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': BOTSI_API_KEY
},
body: JSON.stringify({
paywallId: paywallId,
event: 'paywall_impression',
timestamp: new Date().toISOString()
})
});
} catch (error) {
console.error('Failed to track impression:', error);
}
}
// 4. Validate purchase after Stripe payment
async function validateStripePurchase(profileId, chargeId, amount) {
try {
const response = await fetch(`${BOTSI_BASE_URL}/purchases/stripe/validate`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': BOTSI_API_KEY
},
body: JSON.stringify({
profileId: profileId,
transactionId: chargeId,
amount: amount,
currency: 'usd'
})
});
return await response.json();
} catch (error) {
console.error('Failed to validate purchase:', error);
throw error;
}
}
// Main checkout flow
async function handleCheckout(userEmail) {
// Step 1: Create profile
const profileId = await initializeCheckout(userEmail);
// Step 2: Get pricing
const pricing = await getPricingVariant(profileId);
// Step 3: Display pricing on page
displayPricingUI(pricing.price, pricing.variant);
// Step 4: Track impression
if (pricing.paywallId) {
await trackPaywallImpression(profileId, pricing.paywallId);
}
// Step 5: After user completes Stripe payment
try {
await validateStripePurchase(profileId, stripeChargeId, pricing.price);
} catch (error) {
console.error('Purchase validation failed:', error);
}
}
Important Notes
- API Key Security: Keep your API key on your server and never expose it in client-side code or version control
- Error Handling: Always implement graceful error handling with fallback pricing options
- ID Fields: Use the numeric
idfor impression tracking, not theexternalIDwhich is for UI logic - Profile Creation: Consider caching profiles if the same user visits multiple times within a session
- Testing: Test with sandbox/development credentials before deploying to production
- For more detailed API documentation, see the API reference
Support
For questions about the Custom Web API integration or if you encounter any issues, please refer to the full API reference or contact our support team.