Integration runtime for commerce
Integrations that show their work.
KonnectHub runs the flows between Shopify, your ERP, your CRM and everything else. Webhooks, schedules and events start them. Every firing is recorded, every run is readable, and nothing gets dropped.
- TypeScript or canvas
- Sandboxed workers
- Nothing to host
Executions · acme-store
events 1,284 / held 0 / paused 0
- crm-upsert order.paid WAITING RERUN
- product-to-feed shopify.products.update SUCCEEDED
- erp-invoice POST /webhooks/trigger SUCCEEDED
- sync-inventory cron 0 * * * * SUCCEEDED
- order-received shopify.orders.create SUCCEEDED
- nightly-report cron 0 4 * * * SUCCEEDED
01 / The loop
One loop runs the whole thing.
Write it, publish it, deploy it, point a trigger at it, read what happened. No servers to keep alive in between.
Step 01 / Flow
Write a flow
A flow is a TypeScript class. Each method is a step, and steps run top to bottom. Prefer to drag and drop? Build the same flow as nodes on a canvas.
class OrderReceived extends Workflow
Step 02 / Version
Publish a version
Publishing freezes the draft as a numbered version and bundles it in the background. It can run once the bundle is READY.
v4 · bundle READY
Step 03 / Deployment
Deploy it
A deployment is the flow plus how it runs: which version, its inputs, its limits, and whether it is on. One flow can serve staging, production and every client you have.
concurrency 1 · retries 0 · timeout 300 s
Step 04 / Trigger
Attach a trigger
A webhook, a schedule or an event source. One trigger can drive four deployments. One deployment can answer to a webhook, a schedule and two event sources.
POST /api/v1/webhooks/trigger/<token>
Step 05 / Event
Every firing is an event
Each firing writes exactly one event, even when nothing is listening. "Three deliveries, zero runs" becomes a fact you can see, not a mystery.
event #1285 · 201 Created
Step 06 / Execution
Read the run
Each event starts an execution you can open afterwards: every step with its status, its result, its timing and its logs.
readOrder · SUCCEEDED · 38 ms
02 / Triggers
Three ways in. Nothing slips past.
Every firing writes exactly one event, even when nothing is listening. So "we got three deliveries and ran nothing" is a fact on screen, not a mystery in a log.
- Webhook
- A URL the platform issues. Any method, any body. Optional HMAC check, with SHA256 or SHA512, so you know the sender is real.
- Schedule
- A cron pattern or a single instant, in the time zone you name. 09:00 stays 09:00 when the clocks change.
- Event source
- A named channel that flows and services publish to. Connect Shopify and its topics are already there.
03 / Services & connections
Connect a store once. Your flows never hold the keys.
Connection · Shopify · OAuth2
acme-store
- Shop domain
- acme-store.myshopify.com
- Access token
- ••••••••••••••••encrypted, never in an API response
- Event topics
- shopify.orders.create
- shopify.products.update
- shopify.orders.paid
const { config, credentials } = await this.connection(this.input.store); // resolved by the platform, the moment the flow asks
Credentials, managed
OAuth tokens are refreshed just before a flow needs them. Nothing you write deals with expiry.
Topics, already defined
Shopify’s topics arrive as event sources. Subscribe a deployment like any other.
Webhooks, registered for you
Connect and the provider’s webhooks are set up. Disconnect and they are removed. No callback URLs to paste.
Uninstalls, handled
If a merchant uninstalls, that arrives as an event too, so the connection is torn down cleanly.
BigCommerce connects by token. Anything else with an API becomes a custom service, defined once and used by every flow in the workspace.
04 / Held deliveries
Switch it off. Nothing is lost.
A switched-off deployment holds its deliveries instead of dropping them. Held runs cost nothing, never time out and never start by accident.
Turning it back on does not replay a week of work. Releasing the backlog is a decision you make, and each delivery runs as it arrived: same payload, oldest first.
Try it: switch off, wait, switch on, release
Deployment · order-received
production
Queue 0
Held 0
Runs
- A-1003 SUCCEEDED
- A-1002 SUCCEEDED
- A-1001 SUCCEEDED
Active. Each delivery runs as it arrives.
05 / Executions
When something breaks, read it like a receipt.
Every run is kept as a complete record for 90 days. No guessing which of five systems dropped the order.
- Step by step
- One row per step: its status, what it returned, how long it took, how often it retried. Logs are tied to the step that wrote them.
- Retry the step, not the run
- When a step throws, only that step runs again. Steps that already succeeded keep their results.
- Pause for a person
- A flow can stop and send an approval link. A paused run holds no worker and can wait for days at no cost.
KONNECTHUB · EXECUTION
exec_8f6d · order-received v4
| step | ms |
|---|---|
| readOrder | 38 |
| lookupCustomer | 120 |
| reserveStockretried 1× | 611 |
| createInvoice | 402 |
| notifyWarehouse | 247 |
- INFOreadOrder order A-1001 for 42.5
- WARNreserveStock ERP timed out, retrying
- INFOcreateInvoice invoice INV-2207
result{ invoice: "INV-2207" }
SUCCEEDED1.42 s
06 / Flows
Type it or wire it. Same flow either way.
Developers write a TypeScript class. Everyone else builds on a canvas. Both publish, deploy, trigger and show up in the same list of runs.
import { Workflow } from "konnecthub/flow";
export default class OrderReceived extends Workflow {
readOrder() {
const order = this.payload as { id: string; total: number };
this.log("INFO", `order ${order.id} for ${order.total}`);
return order;
}
async requestApproval() {
const order = await this.getResult<{ id: string; total: number }>("readOrder");
if (order.total < 1000) return;
const hook = await this.pause();
await this.notify.warn(`Approve order ${order.id}?`, hook.resumeUrl);
}
summarise() {
return { seen: true };
}
}lib:pricingShare code between flows as libraries.
subflowCall another flow and wait for its result, or start it and move on.
ws:enrich-order@3Turn your own logic into a node type the whole team can drag in.
07 / Data stores & notifications
State that outlives a run.
Workspace tables with columns you define. Map one system's ids to another's, keep a queue, or hold a lookup table someone edits by hand. Rows can point at rows in other stores.
| shopify_id | erp_id | customer → customers | synced |
|---|---|---|---|
| #5512 | SO-88412 | ada@northwind.co | 14:02:53 |
| #5511 | SO-88411 | li@harbor.shop | 14:02:31 |
| #5510 | SO-88409 | sam@fielder.io | 14:01:58 |
| #5509 | SO-88407 | ada@northwind.co | 14:01:12 |
const ids = store(this, this.input.orderMap);
await ids.insert({ shopify_id, erp_id, customer: matchRef({ email }) });Quiet until it matters.
Tuned to under-report. A single failed run notifies nobody. A connection that stops authenticating does, right away.
- CRITICALDeployment is failing02:15
- INFODeployment recovered21:00
08 / CLI & access
Ship from your terminal. Or from CI.
konnecthub new order-received
✓ flow created, draft linked
konnecthub test
✓ fixtures/a-1001.json 3 steps SUCCEEDED
konnecthub deploy
pushed → published v4 → bundle READY → active
konnecthub logs exec_8f6d --follow
INFO readOrder order A-1001 for 42.5
konnecthub skills
✓ agent instructions refreshed in .claude/skills/
- One draft, two editors
- The CLI and the browser edit the same draft. Someone can type in the editor while you push. The CLI merges.
- Deploys from CI
- Set KONNECTHUB_TOKEN and konnecthub deploy pushes, publishes, waits for READY and switches on.
- Tokens narrow, never widen
- A token can do what you can, minus what you did not grant. Narrow someone’s role and every token they hold narrows with it.
- Sandboxed by default
- Every run gets an isolated Deno worker, with the timeout, memory and CPU its deployment sets.
09 / Done for you
Rather not build it?We will.
Tell us which systems need to talk. Our team scopes the work, builds it on KonnectHub and runs it where you can see every firing and every run.
Invite only
Every workspace starts with a call. After it, we set up a clean workspace for your team and send the invites. Run what we build, or build your own flows in it.
Typical jobs
New Shopify orders land in the ERP
event source → flow → connection
Stock levels sync from the warehouse every hour
schedule → flow → data store
Refunds over $500 wait for a manager
webhook → flow → pause
Customers and orders kept in step with the CRM
event source → subflow → custom service