Skip to main content

Actions

Execute Ductape Actions - pre-built integrations with external services like Stripe, Paystack, and more.

When using a publishable key (frontend), include session (token from your backend) in every request.

Basic Action Execution

import { Ductape } from '@ductape/client';

const ductape = new Ductape({
publishableKey: 'your-publishable-key',
product: 'your-product',
env: 'prd'
});

const sessionToken = getSessionFromYourBackend();

// Execute an action
const result = await ductape.actions.run({
app: 'ductape:stripe',
action: 'create-customer',
input: {
email: 'customer@example.com',
name: 'John Doe'
},
session: sessionToken,
});

console.log('Customer ID:', result.id);

Payment Actions

Stripe Payment Intent

// Create Stripe payment intent
const paymentIntent = await ductape.actions.execute({
action: 'stripe.create-payment-intent',
input: {
amount: 5000, // $50.00 in cents
currency: 'usd',
customer: 'cus_abc123',
automatic_payment_methods: {
enabled: true
}
}
});

console.log('Client Secret:', paymentIntent.client_secret);

Paystack Payment

// Initialize Paystack transaction
const transaction = await ductape.actions.execute({
action: 'paystack.initialize-transaction',
input: {
email: 'customer@example.com',
amount: 50000, // 500 NGN in kobo
currency: 'NGN',
callback_url: 'https://yourapp.com/payment/callback'
}
});

// Redirect user to payment page
window.location.href = transaction.data.authorization_url;

Verify Paystack Payment

// Verify transaction after callback
const verification = await ductape.actions.execute({
action: 'paystack.verify-transaction',
input: {
reference: 'transaction-reference'
}
});

if (verification.data.status === 'success') {
console.log('Payment successful!');
console.log('Amount:', verification.data.amount / 100);
console.log('Customer:', verification.data.customer.email);
}

Subscription Management

Create Stripe Subscription

const subscription = await ductape.actions.execute({
action: 'stripe.create-subscription',
input: {
customer: 'cus_abc123',
items: [
{ price: 'price_monthly_plan' }
],
payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent']
}
});

console.log('Subscription ID:', subscription.id);
console.log('Status:', subscription.status);

Create Paystack Plan

const plan = await ductape.actions.execute({
action: 'paystack.create-plan',
input: {
name: 'Monthly Subscription',
amount: 500000, // 5000 NGN in kobo
interval: 'monthly',
description: 'Premium monthly subscription'
}
});

console.log('Plan Code:', plan.data.plan_code);

Customer Management

List Stripe Customers

const customers = await ductape.actions.execute({
action: 'stripe.list-customers',
input: {
limit: 10
}
});

customers.data.forEach(customer => {
console.log(customer.email, customer.name);
});

List Paystack Customers

const customers = await ductape.actions.execute({
action: 'paystack.list-customers',
input: {
perPage: 20,
page: 1
}
});

customers.data.forEach(customer => {
console.log(customer.email, customer.customer_code);
});

Transaction History

List Paystack Transactions

const transactions = await ductape.actions.execute({
action: 'paystack.list-transactions',
input: {
perPage: 50,
status: 'success'
}
});

transactions.data.forEach(tx => {
console.log(`${tx.customer.email}: ${tx.currency} ${tx.amount / 100}`);
});

Retrieve Stripe Balance

const balance = await ductape.actions.execute({
action: 'stripe.retrieve-balance',
input: {}
});

balance.available.forEach(bal => {
console.log(`${bal.currency.toUpperCase()}: ${bal.amount / 100}`);
});

balance.pending.forEach(bal => {
console.log(`Pending ${bal.currency.toUpperCase()}: ${bal.amount / 100}`);
});

Refunds

Create Stripe Refund

const refund = await ductape.actions.execute({
action: 'stripe.create-refund',
input: {
payment_intent: 'pi_abc123',
amount: 2500, // Partial refund of $25
reason: 'requested_by_customer'
}
});

console.log('Refund Status:', refund.status);

Paystack Refund

const refund = await ductape.actions.execute({
action: 'paystack.refund-transaction',
input: {
transaction: 'transaction-id',
amount: 25000 // Amount in kobo
}
});

console.log('Refund Status:', refund.data.status);

Action Chaining

Execute multiple actions in sequence:

async function processOrder(orderData: any) {
try {
// Create customer
const customer = await ductape.actions.execute({
action: 'stripe.create-customer',
input: {
email: orderData.email,
name: orderData.name
}
});

// Create payment intent
const payment = await ductape.actions.execute({
action: 'stripe.create-payment-intent',
input: {
amount: orderData.total * 100,
currency: 'usd',
customer: customer.id,
metadata: {
orderId: orderData.id
}
}
});

// Send confirmation
await ductape.notifications.send({
channel: 'email',
to: orderData.email,
template: 'order-confirmation',
data: {
orderNumber: orderData.id,
total: orderData.total
}
});

return payment;
} catch (error) {
console.error('Order processing failed:', error);
throw error;
}
}

Error Handling

try {
const result = await ductape.actions.execute({
action: 'stripe.create-payment-intent',
input: {
amount: 5000,
currency: 'usd'
}
});
} catch (error) {
if (error.type === 'StripeCardError') {
console.error('Card was declined');
} else if (error.type === 'StripeInvalidRequestError') {
console.error('Invalid parameters:', error.message);
} else if (error.type === 'StripeAPIError') {
console.error('Stripe API error');
} else if (error.type === 'StripeConnectionError') {
console.error('Network error');
} else {
console.error('Unknown error:', error);
}
}

Retry Logic

async function executeActionWithRetry(
actionConfig: any,
maxRetries = 3,
delay = 1000
) {
let lastError;

for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await ductape.actions.execute(actionConfig);
} catch (error) {
lastError = error;

if (attempt < maxRetries) {
console.log(`Attempt ${attempt} failed, retrying...`);
await new Promise(resolve => setTimeout(resolve, delay * attempt));
}
}
}

throw lastError;
}

// Usage
const result = await executeActionWithRetry({
action: 'paystack.verify-transaction',
input: { reference: 'ref-123' }
});

Complete Payment Flow Example

class PaymentService {
private ductape: Ductape;

constructor() {
this.ductape = new Ductape({
accessKey: process.env.DUCTAPE_ACCESS_KEY!,
product: 'my-shop',
env: 'prd'
});
}

async createStripePayment(amount: number, email: string) {
// Create or retrieve customer
const customer = await this.ductape.actions.execute({
action: 'stripe.create-customer',
input: { email }
});

// Create payment intent
const paymentIntent = await this.ductape.actions.execute({
action: 'stripe.create-payment-intent',
input: {
amount: amount * 100,
currency: 'usd',
customer: customer.id,
automatic_payment_methods: { enabled: true }
}
});

return {
clientSecret: paymentIntent.client_secret,
customerId: customer.id,
paymentIntentId: paymentIntent.id
};
}

async createPaystackPayment(amount: number, email: string) {
const transaction = await this.ductape.actions.execute({
action: 'paystack.initialize-transaction',
input: {
email,
amount: amount * 100, // Convert to kobo
currency: 'NGN',
callback_url: window.location.origin + '/verify'
}
});

return {
authorizationUrl: transaction.data.authorization_url,
reference: transaction.data.reference,
accessCode: transaction.data.access_code
};
}

async verifyPaystackPayment(reference: string) {
const verification = await this.ductape.actions.execute({
action: 'paystack.verify-transaction',
input: { reference }
});

if (verification.data.status === 'success') {
return {
success: true,
amount: verification.data.amount / 100,
customer: verification.data.customer.email,
paidAt: verification.data.paid_at
};
}

return { success: false };
}
}

// Usage
const payments = new PaymentService();

// Stripe flow
const stripePayment = await payments.createStripePayment(99.99, 'user@example.com');
console.log('Client Secret:', stripePayment.clientSecret);

// Paystack flow
const paystackPayment = await payments.createPaystackPayment(5000, 'user@example.com');
window.location.href = paystackPayment.authorizationUrl;

// Later, verify Paystack payment
const verified = await payments.verifyPaystackPayment('reference-123');
if (verified.success) {
console.log('Payment verified!');
}

Next Steps