Skip to main content

Overview

Many organizations use SaaS tools that don’t integrate with each other. Without APIs, teams resort to manual copy-paste between systems — exporting from one tool, reformatting, and entering into another. This is slow, error-prone, and doesn’t scale. Refrain bridges this gap by chaining two runbooks: one to extract data from the source app, and another to input it into the destination app. No custom middleware or integration platform needed.

Example runbook

Step 1: Extract from source
name: extract-from-crm
url: https://crm.example.com/contacts
variables:
  - name: username
    source: secrets
  - name: password
    source: secrets
steps:
  - action: input
    selector: "#email"
    value: "{{ username }}"
  - action: input
    selector: "#password"
    value: "{{ password }}"
  - action: click
    selector: "#login"
  - action: wait
    selector: ".contacts-table"
  - action: click
    selector: ".export-button"
  - action: download
    selector: ".download-csv"
Step 2: Input into destination
name: import-to-billing
url: https://billing.example.com/customers/new
variables:
  - name: company_name
    source: data
  - name: contact_email
    source: data
steps:
  - action: input
    selector: "#companyName"
    value: "{{ company_name }}"
  - action: input
    selector: "#contactEmail"
    value: "{{ contact_email }}"
  - action: click
    selector: "#create"
  - action: wait
    selector: ".success"

Generate and execute

1

Generate the extract runbook

npx @refrainai/cli generate -- \
  --url https://crm.example.com/contacts \
  --goal "Log in and export the contacts list as CSV" \
  --context ./context.md \
  --output ./extract-contacts.yaml
2

Generate the import runbook

npx @refrainai/cli generate -- \
  --url https://billing.example.com/customers/new \
  --goal "Fill in the new customer form and submit" \
  --context ./context.md \
  --output ./import-customers.yaml
3

Run the sync

npx @refrainai/cli execute -- \
  --runbook ./extract-contacts.yaml \
  --secrets ./secrets.json \
  --output-dir ./sync-data

npx @refrainai/cli execute -- \
  --runbook ./import-customers.yaml \
  --data ./sync-data/contacts.csv

Why this works well

  • No middleware — Connect any two web apps without building custom integrations.
  • CSV as the bridge — Extract outputs CSV, import consumes it. Simple and auditable.
  • Self-healing — Both source and destination UI changes are handled automatically.
  • Approval gates — Add human review before importing data into the destination.

What’s next