Create your account
Go to the landing page and click "Get started free". Enter your name, organization name, email, and a password (min 8 characters).
From zero to automation hero. 30 tutorials covering everything from your first workflow to advanced AI-powered automations.
Welcome to A7A — the AI-powered workflow automation engine. This tutorial walks you through account creation and your first look at the editor.
Go to the landing page and click "Get started free". Enter your name, organization name, email, and a password (min 8 characters).
After registration, you'll receive a verification token. Use the /api/auth/verify-email endpoint or click the link in your email to verify.
You'll be redirected to the workflow editor at /app/. The interface has three panels:
Your Free plan includes 3 workflows and 100 executions/month. The badge in the sidebar shows your current plan. Upgrade anytime from /api/subscription/upgrade.
Let's build a simple "Hello World" workflow that triggers manually and logs a message.
Click "+ New Workflow" in the sidebar. Give it a name like "My First Automation".
From the right palette, drag a trigger.manual node onto the canvas. This is your entry point — the workflow starts when you click "Execute".
Drag a flow.log node next to the trigger. Click on the trigger's output dot and drag a connection to the log node's input.
Click the log node to open the inspector. Set the message to: Hello World from A7A!
Click "Save" then "Execute". Watch the execution result in real-time via the execution panel. You should see your message logged.
POST /api/workflows/{id}/executeTriggers are the entry points of your workflows. A7A supports 6 trigger types:
trigger.manual — Start manually from the editor or APItrigger.webhook — Start on HTTP POST/GET to a unique URL ✅ Freetrigger.schedule — Start on a cron schedule ✅ Freetrigger.email — Start when an email is received Starter+trigger.form — Start on form submission Starter+trigger.polling — Start on periodic API polling Starter+trigger.chat — Start from chat interface Professional+Webhooks are the most common trigger. When you add a webhook trigger, A7A generates a unique URL:
POST https://adonissignature.com/a7a/api/trigger/webhook/{workflow_id}
Content-Type: application/json
{
"event": "new_lead",
"data": {
"name": "John Doe",
"email": "john@company.com"
}
}
Schedule triggers use standard cron expressions:
* * * * * — Every minute0 9 * * * — Daily at 9 AM0 */6 * * * — Every 6 hours0 0 * * 1 — Weekly on Monday0 0 1 * * — Monthly on the 1stControl flow nodes let you branch, filter, transform, and manipulate data as it moves through your workflow.
The control.if node has two outputs: true (top) and false (bottom). Use it to route data based on conditions.
Condition: {{ $json.score }} > 70
→ True output: routes to "Save Lead"
→ False output: routes to "Log Rejection"
The control.set node lets you add, modify, or remove fields from the data payload.
Set: status = "qualified"
Set: timestamp = {{ now() }}
Remove: temp_field
The control.http node makes external API calls. Perfect for sending emails, calling third-party APIs, or fetching data.
Method: POST
URL: https://api.sendgrid.com/v3/mail/send
Headers: Authorization: Bearer {{ $credentials.sendgrid }}
Body: {
"to": "{{ $json.email }}",
"subject": "Welcome!",
"text": "Hi {{ $json.name }}"
}
The control.code node executes Python code. Access input via $json and return a dict.
# Calculate lead score
score = 0
if $json.get('company_size', 0) > 100:
score += 30
if $json.get('budget') == 'enterprise':
score += 40
if $json.get('timeline') == 'immediate':
score += 30
return {"json": {"score": score, "qualified": score >= 70}}
control.delay — Pause execution for N secondscontrol.merge — Merge multiple input branchescontrol.filter — Filter items by conditioncontrol.loop — Iterate over arraysflow.switch — Route to multiple outputs by valueflow.sort — Sort arrays by fieldflow.aggregate — Count/sum/avg/min/maxflow.string — String operations (split, replace, format)flow.date — Date operations (add, format, compare)A7A includes a built-in AI agent powered by a 756B parameter model. It can create workflows from natural language, analyze existing workflows, and chat in 16 languages.
Instead of manually building workflows, just describe what you want:
POST /api/agent/create-workflow
Authorization: Bearer {your_token}
{
"prompt": "Create a workflow that monitors my website every 5 minutes and sends me a Telegram alert if it's down"
}
The AI will generate a complete workflow with nodes, connections, and configuration — ready to activate.
The AI agent can answer questions about your workflows:
POST /api/agent/chat
Authorization: Bearer {your_token}
{
"message": "Which of my workflows have errors?",
"session_id": "optional-session-id"
}
The agent can analyze all your workflows and suggest optimizations:
POST /api/agent/auto-optimize
Authorization: Bearer {your_token}
The AI agent understands prompts in: English, Español, Português, Français, Deutsch, Italiano, Nederlands, Русский, 中文, 日本語, 한국어, العربية, हिन्दी, Türkçe, Polski, Tiếng Việt.
POST /api/agent/create-workflow-multilingual
{
"prompt": "Crear un flujo de trabajo que monitoree la seguridad cada 5 minutos",
"lang": "es"
}
Webhooks are the backbone of A7A integrations. They let external systems trigger your workflows in real-time.
Drag a trigger.webhook node onto the canvas. A7A automatically assigns a unique webhook URL.
Add a flow.respond node to send an immediate HTTP response to the caller. This is important for external systems that expect a response.
Status: 200
Body: {"status": "received", "workflow": "lead-capture"}
The incoming data is available as $json in all downstream nodes:
{{ $json.body.name }}
{{ $json.headers.authorization }}
{{ $json.query.campaign }}
Use the control.http node to call any REST API:
Method: GET
URL: https://api.github.com/repos/{{ $json.repo }}
Headers:
Accept: application/vnd.github.v3+json
Authorization: token {{ $credentials.github }}
Store API keys and secrets in the credentials vault:
POST /api/credentials
Authorization: Bearer {your_token}
{
"name": "sendgrid",
"type": "api_key",
"data": {"key": "SG.xxxxx"}
}
Then reference them in nodes as {{ $credentials.sendgrid.key }}
A7A includes a marketplace with 24 pre-built workflow templates across 8 categories. Instantiate any template with one click.
In the sidebar, scroll to "Template Marketplace". Templates are grouped by category:
Click any template in the marketplace sidebar. A confirmation dialog appears.
Click "OK" and A7A creates a new workflow with all nodes and connections pre-configured.
The workflow is yours — modify any node, change the schedule, update credentials, and activate it.
GET /api/marketplace
GET /api/marketplace?tier=free
GET /api/marketplace?category=Security
GET /api/marketplace?search=lead
Created a great workflow? Share it as a template:
POST /api/templates
Authorization: Bearer {your_token}
{
"name": "My Custom Workflow",
"description": "Does something awesome",
"category": "Sales",
"tier": "free",
"nodes": [...],
"connections": {...}
}
A7A is multilingual by design. The AI agent can create and manage workflows in 16 languages.
POST /api/agent/create-workflow-multilingual
Authorization: Bearer {your_token}
{
"prompt": "CRMのリードを自動的にスコアリングするワークフローを作成",
"lang": "ja"
}
GET /api/languages
A7A supports multi-user organizations with role-based access control (RBAC).
POST /api/org/invite
Authorization: Bearer {your_token}
{
"email": "teammate@company.com",
"role": "editor"
}
This generates a unique invitation link valid for 7 days. The invitee creates their account using this link.
POST /api/auth/invite
{
"token": "{invitation_token}",
"email": "teammate@company.com",
"password": "theirpassword123",
"name": "Teammate Name"
}
GET /api/org
Authorization: Bearer {your_token}
Each organization has its own isolated workspace. Workflows, credentials, and executions are scoped to your org — no other org can see or access your data.
API keys let external systems authenticate with A7A without using JWT tokens. Perfect for server-to-server integrations.
POST /api/keys
Authorization: Bearer {your_jwt_token}
{
"name": "Production API",
"scopes": ["read", "write", "execute"]
}
Response:
{
"success": true,
"api_key": "a7a_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"message": "Save this key — it won't be shown again"
}
Pass the API key in the Authorization header:
curl https://adonissignature.com/a7a/api/workflows \
-H "Authorization: ApiKey a7a_xxxxxxxxxxxxxxxx"
DELETE /api/keys/{key_id}
Authorization: Bearer {your_jwt_token}
<form action="https://adonissignature.com/a7a/api/trigger/webhook/{wf_id}" method="POST">
<input name="email" type="email" required>
<input name="name" required>
<button type="submit">Submit</button>
</form>
curl -X POST https://adonissignature.com/a7a/api/workflows/{id}/execute \
-H "Authorization: ApiKey a7a_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"trigger_data": {"event": "test"}}'
curl https://adonissignature.com/a7a/api/executions/{exec_id} \
-H "Authorization: ApiKey a7a_xxxxxxxx"
A7A's expression engine lets you reference and transform data dynamically between nodes using {{ ... }} syntax — similar to n8n.
{{ $json.field_name }}
{{ $json.user.email }}
{{ $node["My Node"].json.result }}
{{ $env.API_KEY }}
{{ now() }}
{{ $execution.id }}
{{ $json.name | upper }}
{{ $json.email | lower }}
{{ $json.description | truncate(100) }}
{{ $json.tags | join(", ") }}
{{ $json.score > 70 ? "qualified" : "rejected" }}
{{ $json.status == "active" ? "✅" : "❌" }}
{{ $json.price * 1.2 }}
{{ $json.quantity * $json.unit_price }}
{{ $json.total / 100 }}
{{ now() }}
{{ now().addDays(7) }}
{{ now().format("YYYY-MM-DD") }}
{{ $json.created_at | daysBetween(now()) }}
Reference data from any node in the execution path:
{{ $node["Fetch User"].json.email }}
{{ $node["HTTP Request"].json.body.data[0].name }}
{{ $credentials.sendgrid.api_key }}
{{ $credentials.stripe.secret_key }}
Schedule triggers let you run workflows on a recurring basis using standard cron expressions.
Cron uses 5 fields: minute hour day-of-month month day-of-week
* * * * * → Every minute
0 * * * * → Every hour (at :00)
0 9 * * * → Daily at 9:00 AM
0 */6 * * * → Every 6 hours
0 0 * * 1 → Every Monday at midnight
0 0 1 * * → 1st of every month at midnight
0 0 1 1 * → January 1st at midnight
*/5 * * * * → Every 5 minutes
0 9 * * 1-5 → Weekdays at 9 AM
*/5 * * * * (every 5 min)0 9 * * * (daily 9 AM)0 9 * * 1 (Mondays 9 AM)0 0 1 * * (1st of month)0 2 * * * (daily 2 AM)0 0 1 */3 * (every 3 months)Schedules run in UTC by default. To run at 9 AM Caracas time (UTC-4), use:
0 13 * * * (9 AM UTC-4 = 13:00 UTC)
Drag a trigger.schedule node. Set the cron expression in the node configuration.
Only active workflows execute on schedule. Click the toggle to activate.
Check the "Recent Executions" panel in the sidebar to see scheduled runs.
A7A provides several nodes for transforming, filtering, sorting, and aggregating data as it flows through workflows.
Add: full_name = {{ $json.first_name }} {{ $json.last_name }}
Add: timestamp = {{ now() }}
Add: status = "processed"
Remove: temporary_token
Rename: old_field → new_field
Filter passes only items that match a condition:
Condition: {{ $json.score }} >= 70
→ Only items with score >= 70 pass through
Sort by: created_at
Direction: descending
→ Items sorted by date, newest first
Operation: sum
Field: amount
Group by: category
→ Returns: [{category: "sales", sum: 1500}, {category: "marketing", sum: 800}]
Process each item in an array sequentially. The output of each iteration feeds the next node.
Input: [{"name":"Alice"}, {"name":"Bob"}, {"name":"Carol"}]
→ Processes 3 items, one at a time
Operation: split
Field: tags
Separator: ","
→ "sales,marketing,lead" becomes ["sales", "marketing", "lead"]
Operation: add
Field: due_date
Value: 7
Unit: days
→ Adds 7 days to the due_date field
Route to different outputs based on a value — like a switch/case statement:
Field: {{ $json.priority }}
Rules:
→ "high" → output 1 (Telegram alert)
→ "medium" → output 2 (Slack message)
→ "low" → output 3 (log only)
→ default → output 4
1. trigger.webhook (new lead arrives)
2. flow.sort (by score, descending)
3. flow.filter (score >= 70)
4. control.set (add "qualified" = true)
5. flow.aggregate (count by source)
6. terminal.leads (save qualified)
7. telegram.send (notify sales team)
Send notifications to Telegram and Slack directly from your workflows. Perfect for alerts, daily reports, and team notifications.
Open Telegram, search for @BotFather, send /newbot, and follow the prompts. You'll receive a bot token like 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11.
Send a message to your bot, then visit https://api.telegram.org/bot{TOKEN}/getUpdates to find your chat ID.
Drag a telegram.send node. Set:
Bot Token: {{ $credentials.telegram_bot_token }}
Chat ID: -1001234567890
Message: 🚨 Alert: {{ $json.event }} at {{ now() }}
Parse Mode: HTML
Go to api.slack.com/apps, create a new app, and add an incoming webhook to your workspace. You'll get a webhook URL.
Use the control.http node to POST to your Slack webhook:
Method: POST
URL: https://hooks.slack.com/services/T.../B.../...
Headers: Content-Type: application/json
Body: {
"text": "🔔 New lead: {{ $json.name }} ({{ $json.email }})",
"channel": "#sales"
}
Message: 🚨 Security Alert
⚠️ Event: {{ $json.event }}
🕐 Time: {{ now() }}
🖥️ Server: {{ $json.server }}
📊 Severity: {{ $json.severity }}
Action required: Check dashboard immediately.
📊 Daily Report — {{ now().format("YYYY-MM-DD") }}
✅ Workflows executed: {{ $json.total_executions }}
❌ Errors: {{ $json.error_count }}
📈 Success rate: {{ $json.success_rate }}%
🏆 Top workflow: {{ $json.top_workflow }}
⚡ Avg execution time: {{ $json.avg_time }}s
Build resilient workflows that handle failures gracefully with error workflows, retries, and fallback logic.
Attach an error workflow to any main workflow. When the main workflow fails, the error workflow runs automatically:
POST /api/workflows/{main_wf_id}/error-workflow
{
"error_workflow_id": "err_wf_id"
}
The error workflow receives:
{
"execution_id": "abc123",
"workflow_id": "main_wf",
"node_id": "HTTP_Request",
"error": "Connection timeout",
"stack": "...",
"timestamp": "2026-08-03T10:00:00Z"
}
Create a new workflow with a manual trigger. Add nodes for:
flow.log — log the error detailstelegram.send — alert the teamterminal.errors — record in error trackerUse the error-workflow API to attach the error workflow to your main workflow.
1. control.http (API call)
2. control.if (status_code == 200?)
→ True: continue workflow
→ False: control.delay (wait 5s) → control.code (increment retry counter)
→ control.if (retry < 3?)
→ True: loop back to HTTP node
→ False: telegram.send (alert failure)
The HTTP node supports configurable timeouts. Set a reasonable timeout to avoid hanging:
Timeout: 30 (seconds)
→ If the API doesn't respond in 30s, the node returns an error
1. control.http (primary API)
2. control.if (success?)
→ True: use primary data
→ False: control.http (fallback API)
→ control.set (mark as "fallback_used")
A7A tracks workflow versions automatically. Every save creates a new version. Professional plans add Git-based versioning for full history and rollback.
Every time you save a workflow, the version counter increments. You can view version history:
GET /api/workflows/{id}
→ Returns current version number
→ "version": 7
GET /api/workflows/{id}/export
→ Returns workflow as JSON (n8n-compatible format)
POST /api/workflows
→ Import by sending the exported JSON
Workflows are stored as JSON files in the workflows-git/ directory. Each save commits a new version:
data/workflows-git/
├── 7fca443e.json (v1 — initial)
├── 5deced20.json (v2 — added trigger)
├── efbd2a21.json (v3 — updated config)
└── ...
GET /api/workflows
→ Loop through and export each one
Commit the exported JSON files to a Git repository for full audit trail.
Import a previous version to restore:
POST /api/workflows
{...exported_workflow_json...}
POST /api/workflows/{id}/share
{
"shared_with": "teammate@company.com",
"permission": "read"
}
When workflows receive high volumes of triggers, the execution queue manages them by priority. Professional plans include queue management.
GET /api/queue
→ List pending queue entries
POST /api/queue/enqueue
{
"workflow_id": "abc123",
"trigger_data": {"event": "new_lead"},
"priority": 0
}
→ Add to queue with high priority
POST /api/queue/process
→ Process the next queue entry
POST /api/executions/{execution_id}/replay
→ Re-runs a failed execution with the same trigger data
Add notes to executions for debugging and audit:
POST /api/executions/{execution_id}/annotations
{
"annotation": "Failed due to API timeout — retry succeeded",
"tag": "resolved"
}
GET /api/metrics
→ Returns: queue_pending count
→ If queue_pending > 100, consider scaling or reducing trigger frequency
Build a complete lead generation machine that captures, scores, routes, and nurtures leads — all automated.
Web Form → Webhook → AI Score → Route
├─ Hot (score>80) → Telegram + CRM
├─ Warm (score>60) → Email sequence
└─ Cold (score<60) → Newsletter
trigger.webhook → flow.respond (200 OK)
→ control.set (add captured_at, source)
→ terminal.leads (save raw lead)
ai.process (classify lead)
Prompt: "Score this lead 0-100 based on:
company size: {{ $json.company_size }}
budget: {{ $json.budget }}
timeline: {{ $json.timeline }}
industry: {{ $json.industry }}"
→ Returns: {"score": 85, "tier": "hot"}
control.if (score > 80?)
→ True: telegram.send ("🔥 HOT LEAD: {{ $json.name }} from {{ $json.company }}")
→ terminal.leads (update status = "hot")
→ control.http (notify CRM)
→ False: control.if (score > 60?)
→ True: control.http (send welcome email)
→ control.delay (3 days)
→ control.http (follow-up email)
→ False: control.http (add to newsletter)
terminal.analytics (track conversion)
→ flow.aggregate (count by tier)
→ flow.log (daily summary)
trigger.webhook — New lead arrivesflow.respond — Instant 200 responsecontrol.set — Add metadataai.process — Score the leadcontrol.if — Score > 80?telegram.send — Alert sales teamterminal.leads — Save to CRMcontrol.http — Send welcome emailcontrol.delay — Wait 3 daysflow.log — Log completionAutomate your CI/CD pipeline with A7A — from Git push to deployment with testing, notifications, and rollback.
Git Push → Webhook → Build → Test → Deploy
├─ Pass → Deploy + Notify
└─ Fail → Alert + Halt
trigger.webhook
URL: /api/trigger/webhook/{wf_id}
GitHub sends: {"ref": "refs/heads/main", "commits": [...]}
control.code
import subprocess
result = subprocess.run(
["npm", "run", "build"],
capture_output=True, text=True, timeout=300
)
return {"json": {
"success": result.returncode == 0,
"output": result.stdout[-500:]
}}
control.code
result = subprocess.run(
["npm", "test", "--", "--ci"],
capture_output=True, text=True, timeout=600
)
return {"json": {
"passed": result.returncode == 0,
"failures": result.stderr[-1000:]
}}
control.if (tests.passed == true)
→ True: control.code (deploy via SSH/rsync)
→ telegram.send ("✅ Deployed: {{ $json.commit }}")
→ False: telegram.send ("❌ Tests failed — deploy halted")
→ terminal.errors (log failure)
control.http (health check)
URL: https://mysite.com/health
→ control.if (status == 200)
→ True: flow.log ("Deploy verified ✅")
→ False: control.code (rollback)
→ telegram.send ("🚨 Deploy failed — rolled back")
The marketplace includes a pre-built "Deployment Pipeline" template (Professional tier). Instantiate it and customize:
Monitor your A7A workflows in real-time with metrics, audit logs, SSE streaming, and per-node data inspection.
GET /api/metrics
→ {
"workflows": {"total": 15, "active": 12},
"executions": {"total": 1234, "success": 1200, "error": 34, "success_rate": 97.2},
"queue_pending": 0,
"rental_subscriptions": 5,
"nodes": 357,
"recent_executions": [...],
"top_workflows": [...]
}
Every action is logged for compliance:
GET /api/audit?limit=50
→ [
{"action": "workflow_created", "entity": "abc123", "timestamp": "..."},
{"action": "workflow_executed", "entity": "abc123", "detail": "success"},
{"action": "workflow_deleted", "entity": "xyz789", "detail": "by admin"},
...
]
Stream logs in real-time via Server-Sent Events:
const sse = new EventSource('/api/logs/stream');
sse.onmessage = (event) => {
const log = JSON.parse(event.data);
console.log(`[${log.level}] ${log.message}`);
};
After execution, inspect what data each node received and produced:
GET /api/executions/{execution_id}/node-data
→ {
"node_order": ["trigger", "set", "http", "log"],
"trigger_data": {"event": "new_lead"},
"error": null,
"started_at": "...",
"finished_at": "..."
}
1. trigger.schedule (every 5 min)
2. terminal.status (check all services)
3. control.if (any down?)
4. → True: telegram.send ("🚨 Service X is down")
5. → False: flow.log ("All services healthy")
GET /api/executions?limit=50
→ Last 50 executions with status, timing, and data
GET /api/executions?workflow_id=abc123&limit=20
→ Last 20 executions of a specific workflow
GET /api/health
→ {"status": "ok", "version": "2.0.0", "nodes": 357, "saas": true}
Use this endpoint in your external monitoring tools (Uptime Robot, Pingdom, etc.) to monitor A7A itself.
Viewer role can access metrics and audit logs but cannot modify workflows — perfect for monitoring dashboards:
Role: viewer
Permissions: workflows (read), executions (read), metrics (read)
Cannot: create, edit, delete, execute
Store API keys, passwords, and secrets securely in the encrypted credentials vault. Reference them in nodes without exposing values.
POST /api/credentials
Authorization: Bearer {your_token}
{
"name": "stripe",
"type": "api_key",
"data": {
"secret_key": "sk_live_abc123...",
"publishable_key": "pk_live_xyz789..."
}
}
control.http node:
Headers:
Authorization: Bearer {{ $credentials.stripe.secret_key }}
Content-Type: application/json
api_key — API key authenticationbearer — Bearer token authbasic — Basic auth (username + password)oauth2 — OAuth 2.0 tokenscustom — Any custom key-value pairsView a decrypted credential (admin only):
GET /api/credentials/{id}/decrypt
Authorization: Bearer {admin_token}
→ Returns the full decrypted data
DELETE /api/credentials/{id}
Authorization: Bearer {your_token}
The HTTP Request node is A7A's most versatile integration tool. It can call any REST API, download files, submit forms, and interact with webhooks.
Method: GET
URL: https://api.github.com/users/octocat
Headers:
Accept: application/vnd.github.v3+json
→ Returns JSON response in $json
Method: POST
URL: https://api.sendgrid.com/v3/mail/send
Headers:
Authorization: Bearer {{ $credentials.sendgrid }}
Content-Type: application/json
Body:
{
"personalizations": [{
"to": [{"email": "{{ $json.email }}"}]
}],
"subject": "Welcome!",
"content": [{"type": "text/plain", "value": "Hi {{ $json.name }}"}]
}
Method: GET
URL: https://api.example.com/search
Query:
q: {{ $json.query }}
page: 1
limit: 50
→ https://api.example.com/search?q=...&page=1&limit=50
Headers:
X-API-Key: {{ $credentials.api_key }}
X-Request-Id: {{ $execution.id }}
User-Agent: A7A/2.0
Accept-Language: es
1. control.http (GET page 1)
2. flow.string (extract next_page URL)
3. control.if (has_next_page?)
4. → True: control.http (GET next page)
→ loop back to step 2
5. flow.aggregate (combine all results)
Method: GET
URL: https://example.com/report.pdf
Response: Binary
→ Returns binary data that can be saved or processed
Timeout: 30 (seconds)
→ If the API doesn't respond in 30s, node returns error
control.if (status_code >= 400)
→ True: handle error (retry, fallback, alert)
→ False: continue with data
application/json — Default for API callsapplication/x-www-form-urlencoded — For form submissionsmultipart/form-data — For file uploadstext/xml — For SOAP/XML APIstext/html — For scrapingBuild a complete e-commerce automation: from order capture to fulfillment, inventory sync, and customer notifications.
Webhook (new order)
→ Record transaction
→ Check inventory
├─ In stock: → Notify warehouse → Generate tracking → Email customer
└─ Out of stock: → Backorder alert → Notify customer
trigger.webhook
→ flow.respond (200 OK)
→ control.set (add order_date, status="received")
→ terminal.transactions (save order)
control.http (GET inventory for items)
→ control.if (all items in stock?)
→ True:
→ control.http (update inventory - decrement)
→ telegram.send ("📦 New order #{{ $json.order_id }}")
→ control.http (generate tracking number)
→ False:
→ telegram.send ("⚠️ Order #{{ $json.order_id }} — items out of stock")
→ control.set (status="backorder")
control.http (POST /send-email)
Body: {
"to": "{{ $json.customer_email }}",
"subject": "Order #{{ $json.order_id }} Confirmed",
"body": "Hi {{ $json.customer_name }}, your order is confirmed. Tracking: {{ $json.tracking }}"
}
trigger.schedule (daily 6 PM)
→ terminal.transactions (get today's orders)
→ flow.aggregate (sum by product, count orders)
→ control.set (format report)
→ telegram.send ("📊 Daily: {{ $json.total }} orders, ${{ $json.revenue }}")
The marketplace includes 3 e-commerce templates:
trigger.webhook (cart abandoned)
→ control.delay (1 hour)
→ control.http (send recovery email)
→ control.delay (24 hours)
→ control.if (cart still abandoned?)
→ True: control.http (send 10% discount email)
→ False: flow.log ("cart recovered ✅")
The Code node executes Python 3 directly in your workflow. Access input data via $json and return a dict with the output.
# Input available as $json
# Return a dict with "json" key
result = {
"json": {
"processed": True,
"original": $json.get("data"),
"timestamp": datetime.now().isoformat()
}
}
return result
# Normalize and clean lead data
raw = $json
cleaned = {
"name": raw.get("name", "").strip().title(),
"email": raw.get("email", "").strip().lower(),
"phone": raw.get("phone", "").replace("-", "").replace(" ", ""),
"company": raw.get("company", "Unknown"),
"source": raw.get("utm_source", "direct"),
"score": 0
}
# Simple scoring
if cleaned["company"] != "Unknown":
cleaned["score"] += 20
if "@" in cleaned["email"]:
cleaned["score"] += 20
if len(cleaned["phone"]) >= 10:
cleaned["score"] += 15
return {"json": cleaned}
import httpx
resp = httpx.get(f"https://api.example.com/users/{$json['user_id']}")
data = resp.json()
return {"json": {
"user": data,
"fetched_at": datetime.now().isoformat()
}}
# Process array of items
items = $json.get("items", [])
results = []
for item in items:
results.append({
"id": item["id"],
"name": item["name"].upper(),
"price": round(item["price"] * 1.2, 2) # add 20% margin
})
return {"json": {"items": results, "count": len(results)}}
httpx — HTTP clientjson — JSON parsingdatetime — Date/timere — Regular expressionshashlib — Hashingsqlite3 — SQLite databasesubprocess — Shell commandspathlib — File pathsmath — Math functionsstatistics — Statisticscollections — Data structurestry:
value = $json["nested"]["deep"]["field"]
except (KeyError, TypeError):
value = None
if value is None:
return {"json": {"error": "Field not found"}, "error": True}
return {"json": {"value": value}}
$json.get() instead of $json["key"] to avoid KeyErrordatetime.now(timezone.utc) for consistent timestampsBeyond simple webhooks and schedules, A7A supports form triggers and polling triggers for more complex integration patterns.
Form triggers generate an HTML form that collects user input and triggers a workflow on submission:
GET /api/trigger/form/{workflow_id}
→ Returns an HTML form
POST /api/trigger/form/{workflow_id}/submit
→ Form submission triggers the workflow
→ Form data available as $json
Drag a trigger.form node. Configure fields:
Fields:
- name (text, required)
- email (email, required)
- message (textarea, required)
- priority (select: low/medium/high)
On form submit, the workflow receives the data:
$json = {
"name": "John Doe",
"email": "john@company.com",
"message": "I need help with...",
"priority": "high"
}
control.if (priority == "high")
→ telegram.send ("🔥 High priority from {{ $json.name }}")
control.http (send auto-reply email)
terminal.leads (save as lead)
Polling triggers periodically check an external API and trigger the workflow when new data is available:
trigger.polling
URL: https://api.github.com/repos/myorg/myrepo/commits
Interval: 300 (5 minutes)
Check: new items since last poll
→ Only triggers when new commits exist
Poll URL: https://api.example.com/messages
Method: GET
Headers: Authorization: Bearer {{ $credentials.api_key }}
Interval: 60 (seconds)
Trigger Condition: {{ $json | length > 0 }}
Dedup Field: id
→ Only triggers when new items (by id) arrive
Email triggers start workflows when emails are received:
trigger.email
Address: automate@yourdomain.com
Filter: subject contains "invoice"
→ $json contains: from, subject, body, attachments
Build an automated revenue tracking system that aggregates income from multiple sources and sends daily/weekly/monthly reports.
Schedule (hourly)
→ Fetch Stripe revenue
→ Fetch PayPal revenue
→ Fetch Bank API
→ Merge all sources
→ Update dashboard
→ Daily summary at 6 PM
trigger.schedule (hourly)
→ control.http (Stripe: GET /v1/balance)
→ control.http (PayPal: GET /v1/reporting/balances)
→ control.http (Bank API: GET /accounts/balance)
control.merge (combine all sources)
→ flow.aggregate:
Operation: sum
Field: amount
Group by: source
→ Returns: [
{source: "stripe", sum: 5420.00},
{source: "paypal", sum: 1280.50},
{source: "bank", sum: 8900.00}
]
terminal.revenue (update dashboard)
Data: {
"total": 15600.50,
"by_source": [...],
"timestamp": {{ now() }},
"period": "hourly"
}
trigger.schedule (daily 6 PM)
→ terminal.revenue (get today's data)
→ control.set (format report)
→ telegram.send:
💰 Daily Revenue Report — {{ $json.date }}
💳 Stripe: ${{ $json.stripe }}
🅿️ PayPal: ${{ $json.paypal }}
🏦 Bank: ${{ $json.bank }}
📊 Total: ${{ $json.total }}
📈 vs yesterday: {{ $json.delta }}%
trigger.schedule (1st of month)
→ terminal.transactions (get month's transactions)
→ control.code (calculate totals, taxes, discounts)
→ control.http (generate PDF invoice)
→ control.http (send to client)
→ terminal.transactions (save invoice record)
The marketplace includes a "Revenue Dashboard Sync" template (Professional tier) that aggregates from multiple sources hourly. Customize it with your payment processor APIs.
Automatically monitor competitor prices, detect changes, and alert your team when you're being undercut.
trigger.schedule (daily 8 AM)
→ terminal.competitors (get competitor URLs)
→ control.code (scrape prices)
→ ai.process (compare to our prices)
→ control.if (undercut detected?)
→ True: telegram.send alert
→ False: flow.log (prices stable)
terminal.competitors
Competitors:
- name: "Competitor A"
url: "https://competitor-a.com/pricing"
products: ["basic", "pro", "enterprise"]
- name: "Competitor B"
url: "https://competitor-b.com/pricing"
products: ["starter", "business"]
control.code
import httpx
from re import findall
results = []
for competitor in $json["competitors"]:
resp = httpx.get(competitor["url"])
# Extract prices (adjust regex per site)
prices = findall(r'\$(\d+)', resp.text)
results.append({
"name": competitor["name"],
"prices": prices
})
return {"json": {"competitor_prices": results}}
ai.process
Prompt: "Compare competitor prices to our prices:
Our prices: {{ $json.our_prices }}
Competitor prices: {{ $json.competitor_prices }}
Return JSON: {
"undercuts": [{competitor, product, their_price, our_price, difference}],
"opportunities": [{product, we_are_cheaper_by}],
"recommendations": "..."
}"
control.if (undercuts found?)
→ True: telegram.send:
🚨 Price Alert
⚠️ Competitor A undercuts us on "Pro" plan:
Their price: $79 | Our price: $99 | Difference: $20
Recommended action: {{ $json.recommendations }}
→ control.http (update pricing spreadsheet)
→ False: flow.log ("No undercuts detected today ✅")
trigger.schedule (weekly Monday)
→ flow.aggregate (all price changes this week)
→ control.set (format report)
→ telegram.send:
📊 Weekly Competitor Report
Changes this week: {{ $json.changes }}
Average undercut: ${{ $json.avg_diff }}
Products monitored: {{ $json.products }}
Use the "Price Competitor Monitor" template (Professional tier) from the marketplace as a starting point.
Automate your SEO content pipeline: from keyword research to AI-generated articles, CMS publishing, and Google indexing.
trigger.schedule (daily 5 AM)
→ terminal.seo (get keyword targets)
→ ai.process (generate article)
→ ai.process (generate meta tags)
→ terminal.cms (publish article)
→ control.http (submit to Google Indexing API)
→ telegram.send ("📝 Published: {{ $json.title }}")
terminal.seo
Keywords:
- "workflow automation"
- "n8n alternative"
- "business process automation"
- "AI workflow builder"
→ Returns keywords with search volume and competition
ai.process
Prompt: "Write a 1500-word SEO-optimized blog post about '{{ $json.keyword }}'.
Requirements:
- Include H2 and H3 headers
- Meta description (155 chars max)
- Target keyword in first paragraph
- Natural keyword density (~1-2%)
- Include 3 internal links to /a7a/tutorials/
- Include call-to-action at the end
Return JSON: {
"title": "...",
"meta_description": "...",
"content": "full HTML article",
"slug": "url-friendly-slug"
}"
terminal.cms
Action: publish
Data:
title: {{ $json.title }}
slug: {{ $json.slug }}
content: {{ $json.content }}
meta_description: {{ $json.meta_description }}
status: published
published_at: {{ now() }}
control.http
Method: POST
URL: https://indexing.googleapis.com/v3/urlNotifications:publish
Headers:
Authorization: Bearer {{ $credentials.google_indexing }}
Body:
{
"url": "https://adonissignature.com/blog/{{ $json.slug }}",
"type": "URL_UPDATED"
}
trigger.schedule (weekly Monday)
→ terminal.seo (get all published URLs)
→ control.http (check Google Search Console API)
→ ai.process (analyze rankings, suggest improvements)
→ terminal.seo (save audit results)
→ telegram.send ("📊 SEO audit complete — {{ $json.insights }}")
terminal.cms (get all published URLs)
→ control.code (generate sitemap.xml)
→ control.http (upload sitemap to server)
→ control.http (ping Google: https://www.google.com/ping?sitemap=...)
Use the "SEO Content Generator" template (Professional tier) from the marketplace.
Build automated backup workflows that protect your data and verify integrity daily.
trigger.schedule (daily 2 AM)
→ terminal.infrastructure (get DB list)
→ control.loop (for each DB)
→ control.code (dump database)
→ control.code (gzip compress)
→ control.http (upload to S3/remote)
→ control.set (record backup metadata)
→ flow.aggregate (backup summary)
→ flow.log (backup complete)
control.code
import subprocess
db_path = $json["db_path"]
backup_name = f"backup_{$json['name']}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.db"
# SQLite backup
subprocess.run(["sqlite3", db_path, f".backup /tmp/{backup_name}"], check=True)
# Compress
subprocess.run(["gzip", f"/tmp/{backup_name}"], check=True)
return {"json": {
"backup_file": f"{backup_name}.gz",
"size": os.path.getsize(f"/tmp/{backup_name}.gz"),
"db": $json["name"]
}}
control.http
Method: PUT
URL: https://backup-server.com/backups/{{ $json.backup_file }}
Headers:
Authorization: Bearer {{ $credentials.backup_server }}
Body: (binary file)
→ Uploads compressed backup
control.code
# Verify backup integrity
import hashlib
backup_path = f"/tmp/{$json['backup_file']}"
with open(backup_path, 'rb') as f:
file_hash = hashlib.sha256(f.read()).hexdigest()
# Check if hash matches expected
expected = $json.get("expected_hash")
if expected and file_hash != expected:
return {"json": {"error": "Hash mismatch — backup corrupted"}, "error": True}
return {"json": {"hash": file_hash, "verified": True}}
control.code
import os
from datetime import datetime, timedelta
backup_dir = "/tmp/backups"
cutoff = datetime.now() - timedelta(days=7)
deleted = []
for fname in os.listdir(backup_dir):
fpath = os.path.join(backup_dir, fname)
mtime = datetime.fromtimestamp(os.path.getmtime(fpath))
if mtime < cutoff:
os.remove(fpath)
deleted.append(fname)
return {"json": {"deleted": deleted, "count": len(deleted)}}
trigger.schedule (quarterly)
→ control.http (download latest backup)
→ control.code (decompress)
→ control.code (restore to test database)
→ control.code (verify data integrity — count rows, check schema)
→ control.if (all checks pass?)
→ flow.log ("✅ Restore test passed")
→ False: telegram.send ("🚨 Backup restore test FAILED")
The marketplace includes a "Backup Verification" template (Starter tier) that checks backup integrity daily and alerts on failure.
Enterprise customers get white-label capabilities, dedicated instances, custom integrations, and SLA guarantees.
On the Enterprise plan, A7A can be fully white-labeled with your brand:
automate.yourcompany.com)Enterprise plans run on a dedicated server instance:
Uptime guarantee: 99.9%
→ Monthly downtime allowance: ~43 minutes
→ Monitoring: 24/7 automated health checks
Response times:
→ Critical: 1 hour
→ High: 4 hours
→ Medium: 24 hours
→ Low: 72 hours
Credits:
→ 99.0-99.9%: 10% credit
→ 95.0-99.0%: 25% credit
→ <95.0%: 50% credit
Enterprise plans include custom node development:
POST /api/enterprise/sso
{
"provider": "okta",
"saml_metadata_url": "https://yourorg.okta.com/app/...",
"domain": "yourcompany.com"
}
→ All users with @yourcompany.com emails
authenticate via SSO
Reach out via admin@adonissignature.com to discuss requirements, pricing, and timeline.
AdonisSignature provisions a dedicated server, configures SSL, and sets up your custom domain.
Export workflows from your current account and import to the enterprise instance. All data, credentials, and history transfer seamlessly.
Set up SSO authentication, configure roles, and invite your team members.
Switch DNS, update webhook URLs, and go live on your dedicated A7A instance.