First Integration
Complete end-to-end integration example with code samples.
Overview
This guide walks through building a complete subscription integration, from initial setup to handling webhooks.
Project Setup
1. Install Dependencies
# Node.js/JavaScript
npm install @azotte/sdk
# Python
pip install azotte-python
# .NET
dotnet add package Azotte.SDK
2. Initialize SDK
// JavaScript/Node.js
import { AzotteClient } from '@azotte/sdk';
const azotte = new AzotteClient({
apiKey: process.env.AZOTTE_API_KEY,
tenantId: process.env.AZOTTE_TENANT_ID,
environment: 'sandbox' // or 'production'
});
# Python
from azotte import AzotteClient
azotte = AzotteClient(
api_key=os.environ['AZOTTE_API_KEY'],
tenant_id=os.environ['AZOTTE_TENANT_ID'],
environment='sandbox'
)
// C#/.NET
using Azotte.SDK;
var azotte = new AzotteClient(new AzotteClientOptions
{
ApiKey = Environment.GetEnvironmentVariable("AZOTTE_API_KEY"),
TenantId = Environment.GetEnvironmentVariable("AZOTTE_TENANT_ID"),
Environment = AzotteEnvironment.Sandbox
});
Complete Integration Flow
1. Customer Registration
// Create customer
const customer = await azotte.customers.create({
email: 'customer@example.com',
name: 'John Doe',
metadata: {
source: 'web_signup'
}
});
2. Subscription Creation
// Create subscription
const subscription = await azotte.subscriptions.create({
customerId: customer.id,
priceId: 'price_premium_monthly',
paymentMethodId: 'pm_card_visa',
startDate: new Date().toISOString()
});
3. Handle Payment
// Process initial payment
const payment = await azotte.payments.create({
subscriptionId: subscription.id,
amount: subscription.price.amount,
currency: subscription.price.currency,
paymentMethodId: subscription.paymentMethodId
});
if (payment.status === 'succeeded') {
console.log('Payment successful, subscription activated');
} else {
console.log('Payment failed:', payment.failureReason);
}
4. Webhook Integration
// Express.js webhook handler
app.post('/webhooks/azotte', express.raw({type: 'application/json'}), (req, res) => {
const sig = req.headers['azotte-signature'];
try {
const event = azotte.webhooks.constructEvent(
req.body,
sig,
process.env.AZOTTE_WEBHOOK_SECRET
);
switch (event.type) {
case 'subscription.created':
handleSubscriptionCreated(event.data);
break;
case 'subscription.canceled':
handleSubscriptionCanceled(event.data);
break;
case 'payment.succeeded':
handlePaymentSucceeded(event.data);
break;
case 'payment.failed':
handlePaymentFailed(event.data);
break;
}
res.json({received: true});
} catch (err) {
console.log('Webhook signature verification failed:', err.message);
res.status(400).send(`Webhook Error: ${err.message}`);
}
});
Frontend Integration
React Component Example
import React, { useState } from 'react';
import { AzotteCheckout } from '@azotte/react';
function SubscriptionPage() {
const [loading, setLoading] = useState(false);
const handleSubscription = async (priceId) => {
setLoading(true);
try {
const result = await AzotteCheckout.open({
priceId: priceId,
customerId: currentUser.id,
successUrl: '/success',
cancelUrl: '/cancel'
});
if (result.success) {
// Redirect to success page or show confirmation
window.location.href = '/subscription/success';
}
} catch (error) {
console.error('Subscription failed:', error);
} finally {
setLoading(false);
}
};
return (
<div>
<h1>Choose Your Plan</h1>
<div className="pricing-cards">
<div className="card">
<h3>Basic Plan</h3>
<p>$9.99/month</p>
<button
onClick={() => handleSubscription('price_basic_monthly')}
disabled={loading}
>
Subscribe
</button>
</div>
<div className="card">
<h3>Premium Plan</h3>
<p>$19.99/month</p>
<button
onClick={() => handleSubscription('price_premium_monthly')}
disabled={loading}
>
Subscribe
</button>
</div>
</div>
</div>
);
}
Testing Your Integration
1. Test with Sample Data
// Use test mode data
const testCustomer = await azotte.customers.create({
email: 'test@example.com',
name: 'Test User'
});
// Use test payment methods
const testPayment = await azotte.paymentMethods.create({
type: 'card',
card: {
number: '4242424242424242', // Test card number
expMonth: 12,
expYear: 2025,
cvc: '123'
}
});
2. Monitor Events
// Check subscription status
const subscription = await azotte.subscriptions.retrieve(subscriptionId);
console.log('Subscription status:', subscription.status);
// List recent payments
const payments = await azotte.payments.list({
subscriptionId: subscriptionId,
limit: 10
});
Error Handling
try {
const subscription = await azotte.subscriptions.create(subscriptionData);
} catch (error) {
if (error.code === 'payment_method_declined') {
// Handle declined payment
showError('Payment method was declined. Please try a different card.');
} else if (error.code === 'subscription_limit_exceeded') {
// Handle subscription limits
showError('Subscription limit reached. Please contact support.');
} else {
// Handle other errors
console.error('Unexpected error:', error);
showError('Something went wrong. Please try again.');
}
}
Next Steps
- Core Concepts - Understand Azotte's data model
- API Reference - Complete API documentation
- Webhooks - Set up real-time event handling
- SDKs - Language-specific guides