How to Sync New Revel POS Customers into a MySQL Loyalty Database

Build a Spojit workflow that runs on a schedule, reads newly added customers from Revel, reshapes their contact and visit details, and upserts them into a MySQL loyalty database for downstream marketing and analytics.

What This Integration Does

Restaurants and retailers that run Revel at the point of sale collect a steady stream of new customers: names, email addresses, phone numbers, and the visit history attached to their profiles. That data is valuable for loyalty programs, win-back campaigns, and analytics, but it lives inside Revel and is hard to query alongside the rest of your stack. This workflow copies each new customer into a MySQL table you control, so your marketing and reporting tools can read a single, clean loyalty source without anyone exporting spreadsheets by hand.

A Schedule trigger runs the workflow on a cron interval (for example every 15 minutes). Each run reads a page of customers from Revel ordered newest-first, transforms the records into the column shape your loyalty table expects, and upserts them into MySQL keyed on a stable customer identifier. Because the write is an upsert, re-running the workflow is safe: a customer already in the table is updated in place rather than duplicated. The loyalty table itself acts as the high-water mark, so you never need to store sync state anywhere else.

Prerequisites

  • A Revel connection in Spojit (API key) with permission to read customers. Add it under Connections -> Add connection.
  • A MySQL connection in Spojit pointing at the database that holds your loyalty table.
  • A loyalty table to write into. This tutorial assumes a table named loyalty_customers with a unique key on the Revel customer id. A sample schema is given in Step 2.
  • Permission to create and run workflows in your Spojit workspace.

Step 1: Add a Schedule trigger

Create a new workflow in the Workflow Designer and add a Trigger node, then set Trigger Type to Schedule. Enter a 5-field Unix cron expression and an IANA timezone. For a quarter-hourly sync during business hours in Sydney, use:

Cron:     */15 * * * *
Timezone: Australia/Sydney

A single Schedule trigger can hold multiple schedules if you want different cadences. The trigger output is { scheduledAt }, which you do not need downstream here. Keep the interval comfortably longer than a single run takes so executions never overlap.

Step 2: Confirm the loyalty table shape

Before mapping data, make sure your destination table can absorb an upsert. The workflow keys on the Revel customer id via a unique index, so a customer who already exists is updated rather than duplicated. A schema that works with the rest of this tutorial looks like this:

CREATE TABLE loyalty_customers (
  revel_customer_id  VARCHAR(64)  NOT NULL,
  first_name         VARCHAR(255),
  last_name          VARCHAR(255),
  email              VARCHAR(320),
  phone_number       VARCHAR(64),
  visit_count        INT,
  last_synced_at     DATETIME,
  UNIQUE KEY uq_revel_customer (revel_customer_id)
);

If you are not sure of the current columns, add a temporary Connector node on the MySQL connector in Direct mode, pick the describe-table tool, set table to loyalty_customers, and run once to inspect the schema. Remove that node once you have confirmed the columns.

Step 3: Read new customers from Revel

Add a Connector node on the Revel connector in Direct mode and choose the list-customers tool. Order newest-first and pull a bounded page so each run stays fast:

limit:    50
offset:   0
ordering: -created_date

The ordering value -created_date returns the most recently created customers first, and limit caps the page so a busy day does not produce an oversized run. The result is a list of customer objects, each carrying fields such as first_name, last_name, email, and phone_number. Because the upsert in Step 5 is idempotent, re-reading customers you have already synced is harmless: they simply update in place. Name this node's output something memorable like revel so you can reference {{ revel.customers }} downstream (use the exact path shown in the run output the first time you test).

Step 4: Reshape each customer with a Transform node

Add a Transform node to map the Revel customer shape onto your loyalty columns. The goal is a clean list of objects whose keys match the table, with a single timestamp stamped onto every row. Map the fields like this:

revel_customer_id -> the customer's id field from Revel
first_name        -> {{ customer.first_name }}
last_name         -> {{ customer.last_name }}
email             -> {{ customer.email }}
phone_number      -> {{ customer.phone_number }}
visit_count       -> the customer's visit/order count field
last_synced_at    -> the current run time

Trim and lowercase the email so analytics can join on it cleanly, and coalesce any missing phone or visit values to a safe default. If you would rather scaffold this quickly, ask Miraxa, the intelligent layer across your automation, something specific like: "Add a Transform node that maps each Revel customer to revel_customer_id, first_name, last_name, email, and phone_number." Then fine-tune the field mapping in the properties panel.

Step 5: Upsert into MySQL

Add a Connector node on the MySQL connector in Direct mode and choose the execute-query tool. An upsert keyed on the unique index keeps the table clean across re-runs. Use a parameterized statement with ? placeholders and pass the values for one customer:

query:
INSERT INTO loyalty_customers
  (revel_customer_id, first_name, last_name, email, phone_number, visit_count, last_synced_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
  first_name = VALUES(first_name),
  last_name  = VALUES(last_name),
  email      = VALUES(email),
  phone_number = VALUES(phone_number),
  visit_count  = VALUES(visit_count),
  last_synced_at = VALUES(last_synced_at);

params: [ "{{ row.revel_customer_id }}", "{{ row.first_name }}", "{{ row.last_name }}", "{{ row.email }}", "{{ row.phone_number }}", "{{ row.visit_count }}", "{{ row.last_synced_at }}" ]

The ? placeholders keep the query parameterized so values are passed safely rather than concatenated into SQL. Because each execute-query call writes one row, wrap this node in a Loop node (see Step 6) so every transformed customer is written in turn. If you prefer to write a single record per call without SQL, the MySQL connector also offers insert-rows and update-rows tools, but the ON DUPLICATE KEY UPDATE pattern above handles both insert and update in one statement.

Step 6: Loop over the transformed customers

Add a Loop node set to ForEach and point it at the list produced by your Transform node (for example {{ transform.rows }}). Inside the loop body, place the MySQL execute-query node from Step 5 and reference the current item as {{ row }}. The loop runs the upsert once per customer, so a page of 50 customers produces 50 upserts. Connect the trigger to the Revel read, the read to the Transform, the Transform to the Loop, and the Loop body to the MySQL node, then save the workflow.

Tips

  • Keep the Revel limit modest (25 to 100). A smaller page per run plus a frequent schedule keeps each execution quick and well under your loop and timeout budgets.
  • Normalize email to lowercase and trim whitespace in the Transform step so downstream marketing tools join on a single canonical value.
  • Stamp last_synced_at from one run-level timestamp rather than per row, so every customer in a run shares the same value and you can audit which run touched them.
  • To enrich each customer with their latest order activity, you can add a Revel list-orders read filtered by date, but only do this if you need fresher visit data than the customer profile already carries.

Common Pitfalls

  • No unique key, duplicate rows. The ON DUPLICATE KEY UPDATE upsert only deduplicates if revel_customer_id has a unique index. Without it, every run inserts fresh duplicates.
  • Pagination blind spot. Ordering newest-first with a fixed limit can miss customers if more than one page is created between runs. Either raise the limit, shorten the schedule interval, or add an offset loop to page through results.
  • Timezone confusion. The Schedule trigger fires in the IANA timezone you set, not your browser's. A cron of 0 9 * * * in Australia/Sydney is a different real-world time than the same cron in UTC.
  • Missing or null fields. Some Revel profiles lack an email or phone. Coalesce nulls in the Transform step so the MySQL insert does not fail on a not-null column.

Testing

Before turning on the schedule, validate on a small scope. Temporarily set the Revel list-customers limit to 5 and run the workflow once with the Run button (you can attach a temporary Manual trigger for this, or just use the designer's run-once control). Inspect the execution to confirm the Transform output keys match your columns and the MySQL node reports rows affected. Query loyalty_customers directly to confirm the five customers landed, then run the workflow a second time and confirm the same five customers are updated in place rather than duplicated. Once the upsert behaves, restore the real limit and enable the Schedule trigger.

Learn More

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.