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_customerswith 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
limitmodest (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_atfrom 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-ordersread 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 UPDATEupsert only deduplicates ifrevel_customer_idhas a unique index. Without it, every run inserts fresh duplicates. - Pagination blind spot. Ordering newest-first with a fixed
limitcan miss customers if more than one page is created between runs. Either raise the limit, shorten the schedule interval, or add anoffsetloop 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 * * *inAustralia/Sydneyis a different real-world time than the same cron inUTC. - 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.