The core idea
Every automation has two parts:- A trigger — an event that happens in your platform (a new job is posted, a user signs up, a payment succeeds, etc.)
- One or more actions — what happens in response (send an email, POST to a webhook, wait 24 hours, call a Cloudflare Worker, etc.)
All available triggers
Triggers are grouped by area of your platform.Jobs
Tip: Use
job.created when you want a single automation for all new jobs. Use job.created.scraper if you want scraper imports handled separately (e.g., no notification email for automated imports).
Users
Applications
Payments & Subscriptions
Custom / External
All available actions
Each step in your workflow is one of these action types. You can chain as many as you need.Send Email
Send a transactional email using your configured email provider. Supports template variables from the trigger payload (e.g.{{title}}, {{email}}, {{company_name}}).
Config fields: To, Subject, Body (HTML)
Example uses:
- Welcome email when a new employer registers
- “Your job has been approved” notification
- Re-engagement email 3 days after a subscription lapses
Send Webhook
POST the trigger payload + your custom data to any external URL. Config fields: URL, HTTP method Example uses:- Sync new users to a CRM (HubSpot, Pipedrive)
- Notify a Slack channel when a premium job is posted
- Send subscription events to a billing dashboard
Wait / Delay
Pause the workflow for a set number of seconds before continuing. Powered by QStash so the delay survives server restarts — you don’t need to keep a process running. Config fields: Seconds Example uses:- Wait 3 days after signup before sending a “how’s it going?” email
- Wait 1 hour after job approval before tweeting about it
- Buffer between sequential webhook calls to avoid rate limits
HTTP Request
Make a fully custom HTTP call — any method, any URL, custom headers. Config fields: URL, Method (GET/POST/PUT/PATCH/DELETE), Headers, Body Example uses:- Call a Circle.so API to grant or revoke community membership
- Hit a third-party API to post on social platforms
- Trigger a GitHub Actions workflow
Send Notification
Send a formatted message to a Discord or Slack channel via webhook. Config fields: Webhook URL, Provider (discord/slack), Message, Title Example uses:- “#new-signups” channel alert with employer details
- “#payments” alert when a subscription is cancelled
- “#jobs” alert when a scraped job is imported
Run Worker
Call a Cloudflare Worker you built yourself. The worker receives the automation context and can do anything — custom logic, database writes, third-party API calls. Config fields: Worker URL Example uses:- AI-generated social post about a new job
- Custom scoring/matching logic for applicants
- Write to a database outside Supabase
- Any future action type you want to add
Condition
Branch the workflow based on a field in the trigger payload. If the condition is not met, the rest of the workflow stops. Config fields: Field, Operator (equals / not_equals / contains / exists / greater_than / less_than / after_date / before_date), Value Example uses:- Only send a Discord alert if
job.salary_typeequalspaid - Only grant Circle access if
subscription.plan_typeequalspremium - Only send a re-engagement email if
user.emailexists - Only import jobs posted after a specific date
Update Record / Create Record
Write directly to your Supabase database as an automation step. Config fields: Table, Data (key-value pairs), Match column + value (for updates) Example uses:- Automatically set
user.approved = truefor users who pay - Create a
notificationsrow when a new application arrives - Update a job’s status when its subscription expires
Fetch Data
Pull data from any external JSON API, RSS feed, or XML endpoint. The fetched items are stored in the pipeline for downstream actions (Filter, Loop, Create Record). Config fields: URL, Method (GET/POST), Format (json / xml / rss), Data Path (for JSON — the dot-notation path to the items array), Headers Example uses:- Pull job listings from an XML feed daily
- Fetch new postings from a partner API
- Import data from any REST endpoint
Filter / Transform
Filter fetched items by rules and map external field names to your internal data model. Lets you control which items make it through and how they map to Kardow fields. Config fields: Filter rules (field + operator + value), Field mapping (10 job fields: title, description, company_name, location, job_type, salary, how_to_apply, url, category, tags), Assign To (user ID), Only Import New (with date field) Operators: equals, not_equals, contains, not_contains, exists, after_date, before_date Example uses:- Only import jobs from today using the
after_dateoperator onpubDate - Map
jobTitlefrom an external feed totitlein your job board - Assign all imported jobs to a specific user account
- Filter out part-time jobs by checking
job_typenot_equalspart-time
For Each Item (Loop)
Iterate over fetched items and run all subsequent actions once per item. Each item’s fields become available as{{field_name}} template variables in downstream actions.
Config fields: None — it automatically iterates over the items from Fetch Data / Filter.
Example uses:
- Create a job record for each item in an imported feed
- Send a notification for each new posting
- Process each row from an API response individually
Template variables
Any text field in an action config supports{{variable}} syntax. Variables come from the trigger payload. Nested access works with dot notation: {{user.email}}, {{job.title}}.
Integration recipes
Circle.so — grant/revoke community access automatically
When a user subscribes, use the HTTP Request action to call the Circle.so API and add them to your community. When they cancel, revoke access.Social platforms — post about new jobs
Use the Run Worker action with a Cloudflare Worker that accepts a job payload and posts to whatever platform you target (Twitter/X via their API, LinkedIn, etc.). Effort: Moderate. You need:- A Cloudflare Worker (50–100 lines of JavaScript)
- API credentials for each platform
- The platform’s OAuth app approved (LinkedIn takes a few days)
job.created, the worker URL is configurable per automation, and you can add a Condition step to only post jobs above a certain salary or from certain categories.
Stripe / payment sync
Automations already fire onsubscription.created, subscription.cancelled, and payment.succeeded from Stripe webhooks. Use the Send Webhook action to forward these events to any third-party tool in real time.
For bidirectional control — e.g., cancelling a subscription from an external tool — use the external API keys system (/api/external) with the subscriptions endpoint.
HubSpot / CRM sync
Scheduled data imports
The data import pipeline lets you automatically pull jobs (or any data) from external sources on a schedule.How it works
A scheduled import automation uses four actions in sequence:Step-by-step setup
- Go to Automations in your dashboard
- Select Scheduled Job Import from the Scheduled category
- Set the trigger interval (e.g. Daily at 6 AM UTC)
- In Fetch Data, paste your source URL and select the data format:
- JSON: Set the data path to the array key (e.g.
results.jobs) - RSS/XML: Items are extracted automatically from
<item>or<entry>tags
- JSON: Set the data path to the array key (e.g.
- In Filter / Transform:
- Add filter rules (e.g.
statusequalsactive,pubDateafter_datetoday) - Map your external fields to Kardow fields (e.g.
jobTitle→title,companyName→company_name) - Set Assign To to the user who should own the imported jobs
- Toggle Only Import New to skip items older than today
- Add filter rules (e.g.
- The For Each Item and Create Record steps are pre-configured
- Activate the automation
Cron setup
Add an hourly cron job (Vercel Cron, GitHub Actions, or any scheduler) that calls:Supported data formats
What Kardow Automations is good at
- Reacting to platform events with zero infrastructure overhead
- Chaining multiple steps including delays (backed by QStash — no cron jobs to manage)
- Connecting to any external API via webhook or HTTP request
- Extending with custom Cloudflare Workers for logic too specific to bake in
- Full run analytics: every execution is logged with status, timing, and error details
Current limitations
Planning for subscriptions, communities & monetization
Resume database access
The payments and paywall system supports plan-gated content today. To gate a resume database:- Create a payment plan with a specific
code(e.g.,resume_access) - Use the Paywall feature to restrict the resume section to subscribers of that plan
- Use an automation (
subscription.created) to send them a welcome email or grant access to external tools
Custom communities (Circle.so or built-in)
Circle.so integration: Works today via HTTP Request actions as described above. Full sync in both directions is possible with one automation per event (subscription.created, subscription.cancelled).
Built-in community features: Not in the current system. Would require new pages and a roles/access layer. The role system (employer, candidate, admin) is extensible — new roles can be added — but a full community module (posts, threads, spaces) would be a separate feature build.
Multi-plan role permissions
The current subscription system supports plan types and job quotas. Expanding to role-based feature flags (e.g., “only users on thecommunity plan can see the forum”) can be done today by:
- Checking
user_subscriptions.plan_typein your pages - Using automations to sync plan type to a
user_metadatafield for fast client-side access
Adding new trigger points
Any existing route can fire an automation in one line:Adding new action types
To add a new action type (e.g.,post_to_twitter):
- Add the key to
AutomationActionTypeinlib/automations/types.ts - Add its label and description to
ACTION_TYPES - Add a
case 'post_to_twitter':block in theexecuteActionswitch inlib/automations/engine.ts - Add a config form in
AutomationsClient.tsx
Security notes
- Automations are scoped to a single organization. You can never trigger another org’s automations.
- All run logs (including payloads) are protected by RLS — only members of the org can read them.
- Webhook URLs and HTTP request targets are user-supplied — validate them in your config and consider allowlisting domains for sensitive actions.
- The trigger endpoint (
/api/automations/trigger) uses admin Supabase access — it should not be called from client-side code.