Connecting Apps to Products
Learn how to connect third-party apps and integrations to your products.
Overview
Apps represent third-party services (like Stripe, SendGrid, Twilio) that your product integrates with. Connecting apps to products allows you to use their actions within your features and features.
Connecting an App
First, connect an app to create an access tag:
- TypeScript
- Java
- Go
- .NET
import Ductape from '@ductape/sdk';
const ductape = new Ductape({
accessKey: 'your-access-key',
});
await ductape.product.init('my-product');
// Connect the app
const access = await ductape.product.app.connect('stripe');
console.log('App connected with access tag:', access);
import app.ductape.sdk.Ductape;
import app.ductape.sdk.core.EnvType;
import app.ductape.sdk.core.RequestContext;
RequestContext auth = new RequestContext(null, null, null, null, 'your-access-key');
Ductape ductape = new Ductape(EnvType.PRODUCTION, auth);
ductape.product.init('my-product');
// Connect the app
Map<String, Object> access = ductape.product.app.connect('stripe');
System.out.println('App connected with access tag:', access);
import (
"context"
"github.com/ductape/ductape/sdk/go/core"
ductapesdk "github.com/ductape/ductape/sdk/go/ductape"
)
auth := core.NewRequestContext("", "", "", "", 'your-access-key')
client, err := ductapesdk.New(core.EnvProduction, auth)
if err != nil {
return err
}
client.product.init('my-product');
// Connect the app
access := client.product.app.connect('stripe');
fmt.Println('App connected with access tag:', access);
using Ductape.Sdk;
using Ductape.Sdk.Core;
var auth = new RequestContext(null, null, null, null, 'your-access-key', null);
var ductape = new Ductape(EnvType.Production, auth);
await ductape.product.init('my-product');
// Connect the app
var access = await ductape.product.app.connect('stripe');
Console.WriteLine('App connected with access tag:', access);
Adding App Configuration
After connecting, add environment-specific configuration:
- TypeScript
- Java
- Go
- .NET
await ductape.product.app.add({
access_tag: 'stripe-payments',
app: 'stripe',
envs: [
{
slug: 'prd',
base_url: 'https://api.stripe.com',
request_type: 'JSON',
active: true,
},
{
slug: 'dev',
base_url: 'https://api.stripe.com',
request_type: 'JSON',
active: true,
},
],
});
ductape.product.app.add(Map.of(
"access_tag", "stripe-payments",
"app", "stripe",
envs: [
Map.of(
"slug", "prd",
"base_url", "https://api.stripe.com",
"request_type", "JSON",
"active", true
),
Map.of(
"slug", "dev",
"base_url", "https://api.stripe.com",
"request_type", "JSON",
"active", true
),
]
));
client.product.app.add({
"access_tag": "stripe-payments",
"app": "stripe",
envs: [
{
"slug": "prd",
"base_url": "https://api.stripe.com",
"request_type": "JSON",
"active": true,
},
{
"slug": "dev",
"base_url": "https://api.stripe.com",
"request_type": "JSON",
"active": true,
},
],
});
await ductape.product.app.add({
["access_tag"] = "stripe-payments",
["app"] = "stripe",
envs: [
{
["slug"] = "prd",
["base_url"] = "https://api.stripe.com",
["request_type"] = "JSON",
["active"] = true,
},
{
["slug"] = "dev",
["base_url"] = "https://api.stripe.com",
["request_type"] = "JSON",
["active"] = true,
},
],
});
App Configuration Fields
| Field | Type | Description |
|---|---|---|
access_tag | string | Unique identifier for this app instance |
app | string | The base app tag |
envs | array | Environment-specific configurations |
Environment Fields
| Field | Type | Description |
|---|---|---|
slug | string | Environment slug (dev, stg, prd) |
base_url | string | API base URL for this environment |
request_type | string | Request format (JSON, XML, etc.) |
active | boolean | Whether this environment is active |
Fetching Connected Apps
Get All Apps
- TypeScript
- Java
- Go
- .NET
const apps = await ductape.product.app.fetchAll();
apps.forEach(app => {
console.log(`${app.access_tag} (${app.app})`);
console.log(`Environments: ${app.envs.map(e => e.slug).join(', ')}`);
});
Map<String, Object> apps = ductape.product.app.fetchAll();
apps.forEach(app => Map.of(
System.out.println(`$Map.of(app.access_tag) ($Map.of(app.app))`);
System.out.println(`Environments: $Map.of(app.envs.map(e => e.slug).join(', '))`);
));
apps := client.product.app.fetchAll();
apps.forEach(app => {
fmt.Println(`${app.access_tag} (${app.app})`);
fmt.Println(`Environments: ${app.envs.map(e => e.slug).join(', ')}`);
});
var apps = await ductape.product.app.fetchAll();
apps.forEach(app => {
Console.WriteLine(`${app.access_tag} (${app.app})`);
Console.WriteLine(`Environments: ${app.envs.map(e => e.slug).join(', ')}`);
});
Get Specific App
- TypeScript
- Java
- Go
- .NET
const app = await ductape.product.app.fetch('stripe-payments');
console.log('App configuration:', app);
Map<String, Object> app = ductape.product.app.fetch('stripe-payments');
System.out.println('App configuration:', app);
app := client.product.app.fetch('stripe-payments');
fmt.Println('App configuration:', app);
var app = await ductape.product.app.fetch('stripe-payments');
Console.WriteLine('App configuration:', app);
Updating App Configuration
- TypeScript
- Java
- Go
- .NET
await ductape.product.app.update('stripe-payments', {
envs: [
{
slug: 'prd',
base_url: 'https://api.stripe.com/v2', // Updated version
request_type: 'JSON',
active: true,
},
],
});
ductape.product.app.update('stripe-payments', Map.of(
envs: [
Map.of(
"slug", "prd",
"base_url", "https://api.stripe.com/v2", // Updated version
"request_type", "JSON",
"active", true
),
]
));
client.product.app.update('stripe-payments', {
envs: [
{
"slug": "prd",
"base_url": "https://api.stripe.com/v2", // Updated version
"request_type": "JSON",
"active": true,
},
],
});
await ductape.product.app.update('stripe-payments', {
envs: [
{
["slug"] = "prd",
["base_url"] = "https://api.stripe.com/v2", // Updated version
["request_type"] = "JSON",
["active"] = true,
},
],
});
Complete Example
- TypeScript
- Java
- Go
- .NET
import Ductape from '@ductape/sdk';
async function setupProductApps() {
const ductape = new Ductape({
accessKey: 'your-access-key',
});
await ductape.product.init('ecommerce-platform');
// Connect payment provider
await ductape.product.app.connect('stripe');
await ductape.product.app.add({
access_tag: 'stripe-payments',
app: 'stripe',
envs: [
{
slug: 'prd',
base_url: 'https://api.stripe.com',
request_type: 'JSON',
active: true,
},
{
slug: 'dev',
base_url: 'https://api.stripe.com',
request_type: 'JSON',
active: true,
},
],
});
// Connect email service
await ductape.product.app.connect('sendgrid');
await ductape.product.app.add({
access_tag: 'sendgrid-email',
app: 'sendgrid',
envs: [
{
slug: 'prd',
base_url: 'https://api.sendgrid.com',
request_type: 'JSON',
active: true,
},
{
slug: 'dev',
base_url: 'https://api.sendgrid.com',
request_type: 'JSON',
active: true,
},
],
});
// Connect SMS service
await ductape.product.app.connect('twilio');
await ductape.product.app.add({
access_tag: 'twilio-sms',
app: 'twilio',
envs: [
{
slug: 'prd',
base_url: 'https://api.twilio.com',
request_type: 'JSON',
active: true,
},
],
});
console.log('All apps connected!');
}
setupProductApps().catch(console.error);
import app.ductape.sdk.Ductape;
import app.ductape.sdk.core.EnvType;
import app.ductape.sdk.core.RequestContext;
async function setupProductApps() Map.of(
RequestContext auth = new RequestContext(null, null, null, null, 'your-access-key');
Ductape ductape = new Ductape(EnvType.PRODUCTION, auth);
ductape.product.init('ecommerce-platform');
// Connect payment provider
ductape.product.app.connect('stripe');
ductape.product.app.add(Map.of(
"access_tag", "stripe-payments",
"app", "stripe",
envs: [
Map.of(
"slug", "prd",
"base_url", "https://api.stripe.com",
"request_type", "JSON",
"active", true
),
Map.of(
"slug", "dev",
"base_url", "https://api.stripe.com",
"request_type", "JSON",
"active", true
),
]
));
// Connect email service
ductape.product.app.connect('sendgrid');
ductape.product.app.add(Map.of(
"access_tag", "sendgrid-email",
"app", "sendgrid",
envs: [
Map.of(
"slug", "prd",
"base_url", "https://api.sendgrid.com",
"request_type", "JSON",
"active", true
),
Map.of(
"slug", "dev",
"base_url", "https://api.sendgrid.com",
"request_type", "JSON",
"active", true
),
]
));
// Connect SMS service
ductape.product.app.connect('twilio');
ductape.product.app.add(Map.of(
"access_tag", "twilio-sms",
"app", "twilio",
envs: [
Map.of(
"slug", "prd",
"base_url", "https://api.twilio.com",
"request_type", "JSON",
"active", true
),
]
));
System.out.println('All apps connected!');
)
setupProductApps();
import (
"context"
"github.com/ductape/ductape/sdk/go/core"
ductapesdk "github.com/ductape/ductape/sdk/go/ductape"
)
async function setupProductApps() {
auth := core.NewRequestContext("", "", "", "", 'your-access-key')
client, err := ductapesdk.New(core.EnvProduction, auth)
if err != nil {
return err
}
client.product.init('ecommerce-platform');
// Connect payment provider
client.product.app.connect('stripe');
client.product.app.add({
"access_tag": "stripe-payments",
"app": "stripe",
envs: [
{
"slug": "prd",
"base_url": "https://api.stripe.com",
"request_type": "JSON",
"active": true,
},
{
"slug": "dev",
"base_url": "https://api.stripe.com",
"request_type": "JSON",
"active": true,
},
],
});
// Connect email service
client.product.app.connect('sendgrid');
client.product.app.add({
"access_tag": "sendgrid-email",
"app": "sendgrid",
envs: [
{
"slug": "prd",
"base_url": "https://api.sendgrid.com",
"request_type": "JSON",
"active": true,
},
{
"slug": "dev",
"base_url": "https://api.sendgrid.com",
"request_type": "JSON",
"active": true,
},
],
});
// Connect SMS service
client.product.app.connect('twilio');
client.product.app.add({
"access_tag": "twilio-sms",
"app": "twilio",
envs: [
{
"slug": "prd",
"base_url": "https://api.twilio.com",
"request_type": "JSON",
"active": true,
},
],
});
fmt.Println('All apps connected!');
}
setupProductApps().catch(console.error);
using Ductape.Sdk;
using Ductape.Sdk.Core;
async function setupProductApps() {
var auth = new RequestContext(null, null, null, null, 'your-access-key', null);
var ductape = new Ductape(EnvType.Production, auth);
await ductape.product.init('ecommerce-platform');
// Connect payment provider
await ductape.product.app.connect('stripe');
await ductape.product.app.add({
["access_tag"] = "stripe-payments",
["app"] = "stripe",
envs: [
{
["slug"] = "prd",
["base_url"] = "https://api.stripe.com",
["request_type"] = "JSON",
["active"] = true,
},
{
["slug"] = "dev",
["base_url"] = "https://api.stripe.com",
["request_type"] = "JSON",
["active"] = true,
},
],
});
// Connect email service
await ductape.product.app.connect('sendgrid');
await ductape.product.app.add({
["access_tag"] = "sendgrid-email",
["app"] = "sendgrid",
envs: [
{
["slug"] = "prd",
["base_url"] = "https://api.sendgrid.com",
["request_type"] = "JSON",
["active"] = true,
},
{
["slug"] = "dev",
["base_url"] = "https://api.sendgrid.com",
["request_type"] = "JSON",
["active"] = true,
},
],
});
// Connect SMS service
await ductape.product.app.connect('twilio');
await ductape.product.app.add({
["access_tag"] = "twilio-sms",
["app"] = "twilio",
envs: [
{
["slug"] = "prd",
["base_url"] = "https://api.twilio.com",
["request_type"] = "JSON",
["active"] = true,
},
],
});
Console.WriteLine('All apps connected!');
}
setupProductApps().catch(console.error);
Using Connected Apps
Once connected, use apps in your features:
- TypeScript
- Java
- Go
- .NET
// Run an action from a connected app (product/env from Ductape constructor)
await ductape.api.run({
app: 'stripe-payments',
action: 'create-charge',
input: {
body: {
amount: 2000,
currency: 'usd',
},
},
});
// Run an action from a connected app (product/env from Ductape constructor)
ductape.api().run(Map<String, Object>.of(
"app", "stripe-payments",
"action", "create-charge",
input: Map.of(
body: Map.of(
"amount", 2000,
"currency", "usd"
)
)
));
import "context"
// Run an action from a connected app (product/env from Ductape constructor)
client.Api.Run(ctx, map[string]any{
"app": "stripe-payments",
"action": "create-charge",
input: {
body: {
"amount": 2000,
"currency": "usd",
},
},
});
// Run an action from a connected app (product/env from Ductape constructor)
await await ductape.Api.RunAsync(new Dictionary<string, object?>
{
["app"] = "stripe-payments",
["action"] = "create-charge",
input: {
body: {
["amount"] = 2000,
["currency"] = "usd",
},
},
});
Best Practices
- Use descriptive access tags -
stripe-payments, not juststripe - Configure all environments - Set up dev, staging, and production
- Keep credentials separate - Use secrets for API keys per environment
- Version base URLs - Include API versions when relevant
- Document integrations - Note which apps are used where
Multiple Instances
You can connect the same app multiple times with different configurations:
- TypeScript
- Java
- Go
- .NET
// US Stripe account
await ductape.product.app.connect('stripe');
await ductape.product.app.add({
access_tag: 'stripe-us',
app: 'stripe',
envs: [/* US config */],
});
// EU Stripe account
await ductape.product.app.connect('stripe');
await ductape.product.app.add({
access_tag: 'stripe-eu',
app: 'stripe',
envs: [/* EU config */],
});
// US Stripe account
ductape.product.app.connect('stripe');
ductape.product.app.add(Map.of(
"access_tag", "stripe-us",
"app", "stripe",
envs: [/* US config */]
));
// EU Stripe account
ductape.product.app.connect('stripe');
ductape.product.app.add(Map.of(
"access_tag", "stripe-eu",
"app", "stripe",
envs: [/* EU config */]
));
// US Stripe account
client.product.app.connect('stripe');
client.product.app.add({
"access_tag": "stripe-us",
"app": "stripe",
envs: [/* US config */],
});
// EU Stripe account
client.product.app.connect('stripe');
client.product.app.add({
"access_tag": "stripe-eu",
"app": "stripe",
envs: [/* EU config */],
});
// US Stripe account
await ductape.product.app.connect('stripe');
await ductape.product.app.add({
["access_tag"] = "stripe-us",
["app"] = "stripe",
envs: [/* US config */],
});
// EU Stripe account
await ductape.product.app.connect('stripe');
await ductape.product.app.add({
["access_tag"] = "stripe-eu",
["app"] = "stripe",
envs: [/* EU config */],
});
See Also
- Products Overview - Product architecture
- Apps - Create and manage apps
- Actions - Use app actions in features
- Secrets - Manage API credentials