Activepieces Integration
Access 200+ pre-built connectors — Slack, Gmail, Google Sheets, Stripe, GitHub, HubSpot, Notion, and more — directly in your workflows. The Activepieces sidecar dynamically loads community pieces and executes actions without requiring them compiled into the engine.
How It Works
The Activepieces integration runs as a sidecar service (Node.js) that dynamically loads and executes Activepieces community pieces on demand. The engine dispatches steps with the ap:// prefix to this sidecar over HTTP.
200+ Connectors
Slack, Gmail, Sheets, Stripe, GitHub, HubSpot, Notion, Airtable, Discord, and growing.
Zero Compilation
Pieces are loaded dynamically at runtime. Add new connectors without rebuilding the engine.
Full Engine Features
Retry, timeout, circuit breaker, credential resolution — all work identically with AP steps.
Architecture
Quick Start
1. Start the sidecar
cd engine/activepieces
npm install
npm start
# Sidecar now listening on http://127.0.0.1:500522. Store credentials
POST /credentials
{
"id": "slack-bot-token",
"kind": "api_key",
"value": "xoxb-your-slack-token",
"tenant_id": "tenant-1"
}3. Use in a workflow
{
"type": "step",
"id": "notify-team",
"handler": "ap://slack.send_channel_message",
"params": {
"auth": {
"access_token": "credentials://slack-bot-token"
},
"props": {
"channel": "#alerts",
"text": "Deployment complete for {{context.data.service}}"
}
}
}Handler Format
Activepieces handlers use the ap:// URI scheme:
ap://<piece-name>.<action-name>
Examples:
ap://slack.send_channel_message
ap://google-sheets.insert_row
ap://gmail.send_email
ap://stripe.create_charge
ap://github.create_issue
ap://hubspot.create_contact
ap://notion.create_page
ap://discord.send_channel_message
ap://airtable.create_record| Component | Format | Examples |
|---|---|---|
| piece-name | lowercase, alphanumeric + hyphens | slack, google-sheets, hubspot |
| action-name | snake_case | send_channel_message, insert_row, create_issue |
Step Parameters
| Field | Type | Description |
|---|---|---|
| auth | object (optional) | Authentication credentials passed verbatim to the piece. Shape is piece-specific. |
| props | object (optional) | Action-specific parameters. Each action defines its own schema. |
Authentication
Each piece defines its own auth shape. Use Orch8's credential system to store secrets and reference them with credentials:// URIs. The engine resolves credentials before dispatching to the sidecar.
Common Auth Patterns
API Token (Slack, Discord, etc.)
"auth": {
"access_token": "credentials://slack-bot-token"
}OAuth2 (Google, GitHub, etc.)
"auth": {
"access_token": "credentials://google-oauth/access_token",
"client_id": "credentials://google-oauth-client/client_id",
"client_secret": "credentials://google-oauth-client/client_secret"
}API Key (Stripe, SendGrid, etc.)
"auth": {
"api_key": "credentials://stripe-live"
}OAuth2 refresh: The sidecar does NOT handle token refresh. Use Orch8's built-in OAuth2 auto-refresh on your credentials (see Credentials guide), or refresh tokens in a preceding workflow step.
Sidecar Setup
Environment Variables
| Variable | Default | Description |
|---|---|---|
| ORCH8_AP_PORT | 50052 | Sidecar listen port |
| ORCH8_AP_HOST | 127.0.0.1 | Bind address (use 0.0.0.0 for Docker) |
| ORCH8_AP_TIMEOUT_MS | 60000 | Per-action execution timeout in ms |
| ORCH8_AP_ALLOWLIST | (none) | Comma-separated piece names. If set, only whitelisted pieces can load. |
| ORCH8_ACTIVEPIECES_URL | http://127.0.0.1:50052/execute | Engine-side: sidecar endpoint URL |
Docker Deployment
# docker-compose.yml
services:
orch8-engine:
image: orch8/engine:latest
environment:
ORCH8_ACTIVEPIECES_URL: http://ap-sidecar:50052/execute
ap-sidecar:
image: orch8/activepieces-worker:latest
environment:
ORCH8_AP_HOST: 0.0.0.0
ORCH8_AP_PORT: 50052
ORCH8_AP_TIMEOUT_MS: 60000
ORCH8_AP_ALLOWLIST: slack,gmail,google-sheets,stripeHealth Check
GET http://127.0.0.1:50052/health
Response:
{ "ok": true, "service": "orch8-activepieces-worker" }Error Handling
The sidecar classifies errors as retryable or permanent. The engine respects this classification for retry decisions.
| Condition | Classification | Behavior |
|---|---|---|
| HTTP 5xx from sidecar | Retryable | Subject to step retry policy |
| HTTP 4xx from sidecar | Permanent | No retry, step fails |
| Network error (ECONNRESET, ETIMEDOUT) | Retryable | Sidecar unreachable, retry later |
| TypeError / SyntaxError in piece code | Permanent | Piece bug, won't succeed on retry |
| Action timeout exceeded | Retryable | Slow external service |
| Unknown error type | Retryable | Fail-open: unknown errors get retried |
Timeouts
Engine-side: 5s connect timeout, 75s total request timeout
Sidecar-side: Per-action timeout (default 60s via ORCH8_AP_TIMEOUT_MS)
Max payload: 4 MiB request body limit
Examples
Send Slack Message
{
"type": "step",
"id": "slack-alert",
"handler": "ap://slack.send_channel_message",
"params": {
"auth": { "access_token": "credentials://slack-bot" },
"props": {
"channel": "#incidents",
"text": "Alert: {{context.data.alert_message}}"
}
},
"retry": { "max_attempts": 3, "initial_backoff": 2000 }
}Insert Google Sheet Row
{
"type": "step",
"id": "log-to-sheet",
"handler": "ap://google-sheets.insert_row",
"params": {
"auth": {
"access_token": "credentials://google-oauth/access_token",
"client_id": "credentials://google-client/client_id",
"client_secret": "credentials://google-client/client_secret"
},
"props": {
"spreadsheet_id": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
"sheet_name": "Leads",
"values": ["{{context.data.name}}", "{{context.data.email}}", "{{context.data.source}}"]
}
}
}Create GitHub Issue
{
"type": "step",
"id": "create-bug-report",
"handler": "ap://github.create_issue",
"params": {
"auth": { "access_token": "credentials://github-pat" },
"props": {
"owner": "myorg",
"repo": "backend",
"title": "Bug: {{context.data.error_type}}",
"body": "Detected at {{context.data.timestamp}}\n\n{{context.data.stack_trace}}",
"labels": ["bug", "auto-created"]
}
}
}Send Email via Gmail
{
"type": "step",
"id": "send-welcome",
"handler": "ap://gmail.send_email",
"params": {
"auth": {
"access_token": "credentials://gmail-oauth/access_token",
"client_id": "credentials://google-client/client_id",
"client_secret": "credentials://google-client/client_secret"
},
"props": {
"to": ["{{context.data.user_email}}"],
"subject": "Welcome to {{context.data.company_name}}",
"body": "Hi {{context.data.user_name}}, thanks for signing up!"
}
}
}Multi-Step: Enrich + Notify
[
{
"type": "step",
"id": "enrich-lead",
"handler": "ap://hubspot.get_contact",
"params": {
"auth": { "api_key": "credentials://hubspot-key" },
"props": { "email": "{{context.data.email}}" }
}
},
{
"type": "step",
"id": "notify-sales",
"handler": "ap://slack.send_channel_message",
"params": {
"auth": { "access_token": "credentials://slack-bot" },
"props": {
"channel": "#sales",
"text": "New lead: {{steps.enrich-lead.output.name}} ({{steps.enrich-lead.output.company}})"
}
}
}
]Limitations
Actions only, no triggers
Activepieces polling/webhook triggers are not supported. Use Orch8's native trigger system for event-driven workflows.
No persistent store
The sidecar's action context store is in-memory only. Data does not persist between invocations. Use Orch8's context.data for state.
OAuth refresh is caller's responsibility
The sidecar does not refresh OAuth tokens. Use Orch8's built-in credential auto-refresh or a preceding workflow step.
File handling limited to data URLs
Files produced by pieces are returned as base64 data URLs, not persisted to storage. Large files should be handled via http_request to cloud storage.
No connection service
Activepieces' connection management is not available. Pass auth directly via params.auth using Orch8's credential system.
Available Pieces
Any published Activepieces community piece works out of the box. The sidecar dynamically installs @activepieces/piece-<name> on first use. Browse available pieces at https://www.activepieces.com/pieces.